I am trying to create EGLImageKHR image from render buffer on a qml application to move a qml application user interface from one device to another device. I tried to use GLES/gl2.h and GLES/gl2ext.h api instead of QOpenGLFunctions. I do not get any error from glGetError() function after glRenderbufferStorage function call but when I try to check render buffer's width,height and internal format from glGetRenderbufferParameteriv function,these do not match with the one that I am trying to set and rest of the functionality is failing, glCheckFramebufferStatus returns 0.
I tried to perform the render buffer creation and the other function calls after rendering, onFrameSwapped and Component.onCompleted. Also I tried to use afterRendering signal slot connection with connect() but all the time I got same results.
Could you please give me some idea to see what I am missing ?
The following are the example content of main.qml,main.cpp and some more required files:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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,&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, &samples);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
qDebug() << "Buff width " << width;
qDebug() << "Buff height " << height;
qDebug() << "Buff format " << format;
qDebug() << "Buff samples " << samples;
GLuint framebuffer;
glGenFramebuffers(1, &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, &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;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////