Создание изображения EGLImageKHR из буфера рендеринга на qt

#egl

#egl

Вопрос:

Я пытаюсь создать изображение EGLImageKHR из буфера рендеринга в приложении qml для перемещения пользовательского интерфейса приложения qml с одного устройства на другое устройство. Я попытался использовать API GLES/gl2.h и GLES/gl2ext.h вместо QOpenGLFunctions. Я не получаю никаких ошибок от функции glGetError() после вызова функции glRenderbufferStorage, но когда я пытаюсь проверить ширину, высоту и внутренний формат буфера рендеринга из функции glGetRenderbufferParameteriv, они не совпадают с тем, который я пытаюсь установить, и остальная функциональность не работает, glCheckFramebufferStatus возвращает 0.

Я попытался выполнить создание буфера рендеринга и другие вызовы функций после рендеринга, onFrameSwapped и Component.OnCompleted. Также я пытался использовать соединение с сигнальным слотом после рендеринга с помощью connect (), но все время получал одни и те же результаты.

Не могли бы вы, пожалуйста, дать мне какую-нибудь идею, чтобы понять, чего мне не хватает?

Ниже приведен пример содержимого main.qml,main.cpp и еще несколько необходимых файлов:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 main.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import WaylandEgl 1.0

Window {
id:mainWindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")

Rectangle
{
    color: "blue"
    anchors.fill: parent
}
Text {
    id: name
    text: qsTr("Hello jii")
}

WaylandEgl
{
    id:wegl
}

onAfterRendering:     wegl.performEglSetup(mainWindow)

/*onFrameSwapped: wegl.performEglSetup(mainWindow)

Component.onCompleted: wegl.performEglSetup(mainWindow)*/

}
 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// main.cpp

 #include <QGuiApplication>
#include <QtQml/QQmlApplicationEngine>
#include <QQuickWindow>
#include <QObject>
#include <QSignalMapper>

#include <QtQml/qqml.h>
#include <QtQml/QQmlEngine>
#include "wl_egl.h"

int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
QGuiApplication app(argc, argv);

qmlRegisterType<WaylandEgl>("WaylandEgl", 1, 0, "WaylandEgl");

QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

return app.exec();

}
 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
wl_egl.h

 #ifndef WL_EGL_H
#define WL_EGL_H

#include <QWindow>
#include <QWaylandCompositor>
#include <QQuickWindow>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#include <gbm.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <drm_fourcc.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <wayland-client.h>

#include <QObject>

class WaylandEgl : public QObject
{
Q_OBJECT
public:
explicit WaylandEgl(QObject* parent = nullptr) : QObject(parent){}
//WaylandEgl();
Q_INVOKABLE int performEglSetup(QWindow *window);
};

#endif // WL_EGL_H
 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// wl_egl.cpp

 #include "wl_egl.h"
#include <stdio.h>

#include <QWaylandSurface>
#include <QGuiApplication>
#include <qpa/qplatformnativeinterface.h>
#include <QDebug>
#include <QScreen>
#include <QWindow>
#include <QQuickWindow>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QGLFormat>
#include <QtWaylandClient/QWaylandClientExtension>
#include <EGL/egl.h>
#include <gbm.h>
#include <EGL/eglplatform.h>
#include <wayland-client.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#include <gbm.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <drm_fourcc.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-client-protocol.h>
#include <wayland-egl.h>

static struct wl_display *display = nullptr;
static struct wl_compositor *compositor = nullptr;
static struct wl_shell *shell = nullptr;
static struct wl_surface *surface = nullptr;
static struct wl_shell_surface *shell_surface = nullptr;
static struct wl_egl_window *egl_window = nullptr;
static EGLDisplay m_display = nullptr;
static EGLConfig m_config = nullptr;
static EGLContext m_context = nullptr;
static EGLSurface m_surface = nullptr;
PFNEGLCREATEIMAGEKHRPROC CreateImageKHR;
//static struct zwp_linux_dmabuf_v1 *dmabuf = nullptr;

static const char *get_egl_error()
{
switch (eglGetError()) {
case EGL_SUCCESS:
return "EGL_SUCCESS";
case EGL_NOT_INITIALIZED:
return "EGL_NOT_INITIALIZED";
case EGL_BAD_ACCESS:
return "EGL_BAD_ACCESS";
case EGL_BAD_ALLOC:
return "EGL_BAD_ALLOC";
case EGL_BAD_ATTRIBUTE:
return "EGL_BAD_ATTRIBUTE";
case EGL_BAD_CONTEXT:
return "EGL_BAD_CONTEXT";
case EGL_BAD_CONFIG:
return "EGL_BAD_CONFIG";
case EGL_BAD_CURRENT_SURFACE:
return "EGL_BAD_CURRENT_SURFACE";
case EGL_BAD_DISPLAY:
return "EGL_BAD_DISPLAY";
case EGL_BAD_SURFACE:
return "EGL_BAD_SURFACE";
case EGL_BAD_MATCH:
return "EGL_BAD_MATCH";
case EGL_BAD_PARAMETER:
return "EGL_BAD_PARAMETER";
case EGL_BAD_NATIVE_PIXMAP:
return "EGL_BAD_NATIVE_PIXMAP";
case EGL_BAD_NATIVE_WINDOW:
return "EGL_BAD_NATIVE_WINDOW";
case EGL_CONTEXT_LOST:
return "EGL_CONTEXT_LOST";
default:
return "EGL_???";
}
}

int WaylandEgl::performEglSetup(QWindow *window)
{
QPlatformNativeInterface * nativeInterface = QGuiApplication::platformNativeInterface();

if (nativeInterface)
{
    qDebug() << "App is running on:" << QGuiApplication::platformName() ;

    QQuickWindow *quick_wind = qobject_cast<QQuickWindow *>(window);

    if (quick_wind->handle())
    {

        qDebug() << "Window:" << quick_wind;
        qDebug() << "Window Surface Type:" << quick_wind->surfaceType();

        m_display =  reinterpret_cast<EGLDisplay>
                (reinterpret_cast<void*>(nativeInterface->nativeResourceForIntegration("egldisplay")));

        if (m_display)
        {
            qDebug() << "Egl Display is " << m_display;
            EGLSurface eglSurface = eglGetCurrentSurface(EGL_READ);
            qDebug() << "Egl Surface" << eglSurface;
            EGLContext eglContext = eglGetCurrentContext();
            qDebug() << "Egl Context" << eglContext;
            EGLDisplay mTempDisp = eglGetCurrentDisplay();
            qDebug() << "Temp disp" << mTempDisp;
        }
        else
        {
            qDebug() << "Egl Display not get";
        }


        QOpenGLContext * openglContext;
        if (quick_wind->openglContext())
        {
            qDebug() << "Opengl context " ;
            openglContext = quick_wind->openglContext();
        }
        else
        {
            qDebug() << "No openglt context";
            openglContext = QOpenGLContext::currentContext();
            qDebug() << "Open gl contex"<< openglContext;

            if (!openglContext)
            {
                openglContext = QOpenGLContext::globalShareContext();
                qDebug() << "Open gl contex after null"<< openglContext;
            }
        }

        if (openglContext)
        {
            EGLConfig eglConfig = nativeInterface->nativeResourceForContext("eglconfig",openglContext);
            qDebug() << "EGL config" << eglConfig;

            EGLContext eglcontext = nativeInterface->nativeResourceForContext("eglcontext", openglContext);
            qDebug() << "EGL eglcontext" << eglcontext;
        }
        else
        {
            qDebug() << "No opengl context";
            return -1;
        }
    }
    else
    {
        qDebug() << "No Window" ;
        return -1;
    }

    GLuint source;
    glGenRenderbuffers(1,amp;source);
    glBindRenderbuffer(GL_RENDERBUFFER, source);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, static_cast<GLsizei>(quick_wind->width()),
                          static_cast<GLsizei>(quick_wind->height()));


    if (glGetError()==GL_NO_ERROR)
    {
        qDebug() << "Render buff storage is OK" << glGetError();
    }
    else
    {
        qDebug() << "Render buff storage error is " << glGetError();
    }

    GLint samples, format , width, height;

    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, amp;samples);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, amp;format);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, amp;width);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, amp;height);

    qDebug() << "Buff width " << width;
    qDebug() << "Buff height " << height;
    qDebug() << "Buff format " << format;
    qDebug() << "Buff samples " << samples;

    GLuint framebuffer;
    glGenFramebuffers(1, amp;framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);

    if (glGetError()==GL_NO_ERROR)
    {
        qDebug() << "Frame buff storage is OK" << glGetError();
    }
    else
    {
        qDebug() << "Frame buff storage error is " << glGetError();
    }


    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    switch(status)
    {
        case GL_FRAMEBUFFER_COMPLETE:
            qDebug("Framebuffer verified complete.");
            break;
        case GL_FRAMEBUFFER_UNSUPPORTED:
            qDebug("GL_FRAMEBUFFER_UNSUPPORTED");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            qDebug("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ");
            break;
        default:
            qDebug("Other framebuffer error: %i", status);
            break;
    }

    glDeleteFramebuffers(1, amp;framebuffer);

    CreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");

    if (!CreateImageKHR)
    {
        qDebug() << "No image khr";
        return -1;
    }

    EGLImageKHR image =
                CreateImageKHR(m_display, m_context, EGL_GL_RENDERBUFFER_KHR,
                                  reinterpret_cast<EGLClientBuffer>(source), nullptr);

    if (image == EGL_NO_IMAGE_KHR)
    {
        qDebug("failed to make image from target buffer: %s", get_egl_error());
        return -1;
    }

    qDebug() << "Image is "<< image;
}
return 0;

}
 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Комментарии:

1. Здравствуйте, я также добавил следующие строки для целей отладки после вызова code glBindRenderbuffer if (glIsRenderbuffer(source)) {qDebug() << «Источник — буфер рендеринга»; } else { qDebug() << «Источник не является буфером рендеринга»; } code и я вижу следы «Источник не является буфером рендеринга». С уважением

Ответ №1:

Есть обновление. В настоящее время мне удается получить правильные значения из glGetRenderbufferParameteriv для ширины, высоты и внутреннего формата, изменив некоторые файлы следующим образом:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

main.qml

импорт QtQuick 2.0 импорт QtQuick.Окно 2.0 импортирует QtWayland.Compositor 1.0 импорт WaylandEgl 1.0

Window { id: MainWindow видимый: true ширина: 640 высота: 480 заголовок: qsTr («Привет, мир»)

 Rectangle
{
    color: "blue"
    anchors.fill: parent
    width: parent.width
    height: parent.height
}
Text {
    id: name
    text: qsTr("Hello jii")
}

WaylandEgl
{
    id:wegl
}

//onAfterRendering:     wegl.performEglSetup(mainWindow)

//Component.onCompleted: wegl.performEglSetup(mainWindow)

/*onFrameSwapped: wegl.performEglSetup(mainWindow)

Component.onCompleted: wegl.performEglSetup(mainWindow)*/
 

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// wl_egl.h

 #ifndef WL_EGL_H
#define WL_EGL_H

#include <QWindow>
#include <QWaylandCompositor>
#include <QQuickWindow>
#include <QOpenGLFunctions>
#include <QQuickItem>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#include <gbm.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <drm_fourcc.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <wayland-client.h>

#include <QObject>

class WaylandEgl : public QQuickItem
{
    Q_OBJECT
public:
    explicit WaylandEgl(QObject* parent = nullptr) ;
    //WaylandEgl();
    Q_INVOKABLE int performEglSetup();
    QQuickWindow * mwindow;


private slots:
    void handleWindowChanged(QQuickWindow *win);

public slots:
    void paint();
    void cleanup();
    void sync();
};


#endif // WL_EGL_H
 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 #include "wl_egl.h"
#include <stdio.h>

#include <QWaylandSurface>
#include <QGuiApplication>
#include <qpa/qplatformnativeinterface.h>
#include <QDebug>
#include <QScreen>
#include <QWindow>
#include <QQuickWindow>
//#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QGLFormat>
#include <QtWaylandClient/QWaylandClientExtension>
#include <EGL/egl.h>
#include <gbm.h>
#include <EGL/eglplatform.h>
#include <wayland-client.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#include <gbm.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <drm_fourcc.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-client-protocol.h>
#include <wayland-egl.h>


static EGLDisplay m_display = nullptr;
static EGLConfig m_config = nullptr;
static EGLContext m_context = nullptr;
static PFNEGLCREATEIMAGEKHRPROC CreateImageKHR;
//static struct zwp_linux_dmabuf_v1 *dmabuf = nullptr;

static const char *get_egl_error()
{
    switch (eglGetError()) {
        case EGL_SUCCESS:
            return "EGL_SUCCESS";
        case EGL_NOT_INITIALIZED:
            return "EGL_NOT_INITIALIZED";
        case EGL_BAD_ACCESS:
            return "EGL_BAD_ACCESS";
        case EGL_BAD_ALLOC:
            return "EGL_BAD_ALLOC";
        case EGL_BAD_ATTRIBUTE:
            return "EGL_BAD_ATTRIBUTE";
        case EGL_BAD_CONTEXT:
            return "EGL_BAD_CONTEXT";
        case EGL_BAD_CONFIG:
            return "EGL_BAD_CONFIG";
        case EGL_BAD_CURRENT_SURFACE:
            return "EGL_BAD_CURRENT_SURFACE";
        case EGL_BAD_DISPLAY:
            return "EGL_BAD_DISPLAY";
        case EGL_BAD_SURFACE:
            return "EGL_BAD_SURFACE";
        case EGL_BAD_MATCH:
            return "EGL_BAD_MATCH";
        case EGL_BAD_PARAMETER:
            return "EGL_BAD_PARAMETER";
        case EGL_BAD_NATIVE_PIXMAP:
            return "EGL_BAD_NATIVE_PIXMAP";
        case EGL_BAD_NATIVE_WINDOW:
            return "EGL_BAD_NATIVE_WINDOW";
        case EGL_CONTEXT_LOST:
            return "EGL_CONTEXT_LOST";
        default:
            return "EGL_???";
    }
}

WaylandEgl::WaylandEgl(QObject* parent )
{
    connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
}

void WaylandEgl::handleWindowChanged(QQuickWindow *win)
{
    qDebug() << "function" << __FUNCTION__ << "line " << __LINE__;
    if (win)
    {
        qDebug() << "function" << __FUNCTION__ << "line " << __LINE__ << "win" << win;
        connect(win, SIGNAL(afterRendering()), this, SLOT(paint()), Qt::DirectConnection);
        //connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
        win->setClearBeforeRendering(false);
        mwindow = win;
    }
}

void WaylandEgl::paint()
{
    qDebug() << "function" << __FUNCTION__ << "line " << __LINE__ << "win" << mwindow;

    performEglSetup();
}

void WaylandEgl::sync()
{
    qDebug() << "function" << __FUNCTION__ << "line " << __LINE__;
}

void WaylandEgl::cleanup()
{
    qDebug() << "function" << __FUNCTION__ << "line " << __LINE__;
}

int WaylandEgl::performEglSetup()
{
    QPlatformNativeInterface * nativeInterface = QGuiApplication::platformNativeInterface();

    if (nativeInterface)
    {
        qDebug() << "App is running on:" << QGuiApplication::platformName() ;

        if (mwindow->handle())
        {

            qDebug() << "Window:" << mwindow;
            qDebug() << "Window Surface Type:" << mwindow->surfaceType();

            m_display =  reinterpret_cast<EGLDisplay>
                    (reinterpret_cast<void*>(nativeInterface->nativeResourceForIntegration("egldisplay")));

            if (m_display)
            {
                qDebug() << "Egl Display is " << m_display;
            }
            else
            {
                qDebug() << "Egl Display not get";
                //return -1;
            }


            QOpenGLContext * openglContext;
            if (mwindow->openglContext())
            {
                qDebug() << "Opengl context " ;
                openglContext = mwindow->openglContext();
            }
            else
            {
                qDebug() << "No openglt context";
                openglContext = QOpenGLContext::currentContext();
                qDebug() << "Open gl contex"<< openglContext;

                if (!openglContext)
                {
                    openglContext = QOpenGLContext::globalShareContext();
                    qDebug() << "Open gl contex after null"<< openglContext;
                }
            }

            if (openglContext)
            {
                m_config = nativeInterface->nativeResourceForContext("eglconfig",openglContext);
                qDebug() << "EGL config" << m_config;

                m_context = nativeInterface->nativeResourceForContext("eglcontext", openglContext);
                qDebug() << "EGL eglcontext" << m_context;
            }
            else
            {
                qDebug() << "No opengl context";
                return -1;
            }
        }
        else
        {
            qDebug() << "No Window sheet" ;
            return -1;
        }

        GLuint source;
        glGenRenderbuffers(1,amp;source);
        glBindRenderbuffer(GL_RENDERBUFFER, source);

        if (glGetError()==GL_NO_ERROR)
        {
            qDebug() << "Render buff storage is OK" << glGetError();
        }
        else
        {
            qDebug() << "Render buff storage error is " << glGetError();
        }

        if (glIsRenderbuffer(source))
        {
            qDebug() << "Source is Render buffer";
        }
        else
        {
            qDebug() << "Source is not Render buffer";
        }

        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, static_cast<GLsizei>(mwindow->width()),
                              static_cast<GLsizei>(mwindow->height()));


        if (glGetError()==GL_NO_ERROR)
        {
            qDebug() << "Render buff storage is OK" << glGetError();
        }
        else
        {
            qDebug() << "Render buff storage error is " << glGetError();
        }

        GLint samples, format , width, height;

        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, amp;samples);
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, amp;format);
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, amp;width);
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, amp;height);

        qDebug() << "Buff width " << width;
        qDebug() << "Buff height " << height;
        qDebug() << "Buff format " << format;
        qDebug() << "Buff samples " << samples;

        GLuint framebuffer;
        glGenFramebuffers(1, amp;framebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);

        if (glGetError()==GL_NO_ERROR)
        {
            qDebug() << "Frame buff storage is OK" << glGetError();
        }
        else
        {
            qDebug() << "Frame buff storage error is " << glGetError();
        }


        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        switch(status) {
            case GL_FRAMEBUFFER_COMPLETE:
                qDebug("Framebuffer verified complete.");
                break;
            case GL_FRAMEBUFFER_UNSUPPORTED:
                qDebug("GL_FRAMEBUFFER_UNSUPPORTED");
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
                qDebug("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ");
                break;
            default:
                qDebug("Other framebuffer error: %i", status);
                break;
        }

        glDeleteFramebuffers(1, amp;framebuffer);

        CreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");

        if (!CreateImageKHR)
        {
            qDebug() << "No image khr";
            return -1;
        }

        EGLImageKHR image =
                    CreateImageKHR(m_display, m_context, EGL_GL_RENDERBUFFER_KHR,
                                      reinterpret_cast<EGLClientBuffer>(source), nullptr);

        if (image == EGL_NO_IMAGE_KHR)
        {
            qDebug("failed to make image from target buffer: %s", get_egl_error());
            return -1;
        }

        qDebug() << "Image is "<< image;

        glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
        if (glGetError()==GL_NO_ERROR)
        {
            qDebug() << "glEGLImageTargetRenderbufferStorageOES buff is OK" << glGetError();
        }
        else
        {
            qDebug() << "glEGLImageTargetRenderbufferStorageOES buff error is " << glGetError();
        }
    }
    return 0;
}
 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Итак, на данный момент я могу успешно успешно создать изображение EGLImageKHR. Мне кажется, что это 2D-массив (у меня нет дополнительной информации), но пока я не смог найти способ создать из него какой-нибудь файл .png.

Есть ли какие-либо идеи, как им управлять? С уважением