diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-06-21 21:24:17 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-06-21 21:24:17 -0700 |
commit | ba3f0c18fb527551f039ae104919a9cacdfbf9c3 (patch) | |
tree | 4cc04cfb69a28c4a1c99c412e78448b8bdff3d28 | |
parent | a6cd1146c4144f8fa85174b97db70678af0ab939 (diff) |
Wayland: move drawing from swapbuffers to window surface flush
We don't actually swap buffers under wayland; drawing is more directly
under client control. So use the window surface flush code to get
drawing from our private FBO into the window surface itself by binding
the renderbuffer colorbuffer before we actually draw the texture to the
output.
-rw-r--r-- | src/gui/egl/qegl_wayland.cpp | 23 | ||||
-rw-r--r-- | src/gui/egl/qeglcontext_p.h | 2 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 2 | ||||
-rw-r--r-- | src/opengl/qgl_egl.cpp | 18 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 1 | ||||
-rw-r--r-- | src/opengl/qgl_waylandegl.cpp | 16 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer.cpp | 1 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_waylandgl.cpp | 247 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_waylandgl_p.h | 2 |
9 files changed, 104 insertions, 208 deletions
diff --git a/src/gui/egl/qegl_wayland.cpp b/src/gui/egl/qegl_wayland.cpp index 367ec9d376..1c6302ecba 100644 --- a/src/gui/egl/qegl_wayland.cpp +++ b/src/gui/egl/qegl_wayland.cpp @@ -59,14 +59,13 @@ _glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES = 0; _glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES = 0; _eglExportDRMImageMESA qt_eglExportDRMImageMESA = 0; -bool QEglContext::makeCurrent(EGLImageKHR img) +bool QEglContext::makeCurrent() { if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current"; return false; } - currentImage = img; current = true; setCurrentContext(apiType, this); @@ -78,24 +77,9 @@ bool QEglContext::makeCurrent(EGLImageKHR img) bool ok = eglMakeCurrent(QEgl::display(), NULL, NULL, ctx); if (!ok) - qWarning() << "QEglContext::makeCurrent(" << img << "):" << + qWarning() << "QEglContext::makeCurrent() failed:" << QEgl::errorString(); - glGenFramebuffers(1, &wl_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, wl_fbo); - - glGenRenderbuffers(1, &wl_color_rbo); - glBindRenderbuffer(GL_RENDERBUFFER, wl_color_rbo); - QEgl::glEGLImageTargetRenderbufferStorage(GL_RENDERBUFFER, currentImage); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, wl_color_rbo); - - glViewport(0, 0, 100, 100); - glClearColor(1.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - glFinish(); - return ok; } @@ -189,7 +173,8 @@ EGLImageKHR QEgl::createImage(QPaintDevice *device, EGLConfig cfg, attribs[1] = widget->width(); attribs[3] = widget->height(); } else { - qWarning("can only create pixmap and widget images\n"); + qWarning("can only create pixmap and widget images (%d)\n", + devType); return EGL_NO_SURFACE; } diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h index 85d3982c4d..236c0a761e 100644 --- a/src/gui/egl/qeglcontext_p.h +++ b/src/gui/egl/qeglcontext_p.h @@ -83,7 +83,7 @@ public: #ifndef Q_WS_WAYLAND bool makeCurrent(EGLSurface surface); #else - bool makeCurrent(EGLImageKHR img); + bool makeCurrent(); #endif bool doneCurrent(); bool lazyDoneCurrent(); diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 17433cec33..2f8d93d60b 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1643,8 +1643,6 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) eglContext = 0; #ifndef Q_WS_WAYLAND eglSurface = EGL_NO_SURFACE; -#else - eglImage = EGL_NO_IMAGE_KHR; #endif #endif fbo = 0; diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index ffe3ba0db6..50ac71c1f5 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -174,8 +174,6 @@ void QGLContext::reset() d->eglContext = 0; #ifndef Q_WS_WAYLAND d->eglSurface = EGL_NO_SURFACE; -#else - d->eglImage = EGL_NO_IMAGE_KHR; #endif d->crWin = false; d->sharing = false; @@ -219,12 +217,12 @@ void QGLContext::makeCurrent() void QGLContext::makeCurrent() { Q_D(QGLContext); - if (!d->valid || !d->eglContext || d->eglImage == EGL_NO_IMAGE_KHR) { - qWarning("QGLContext::makeCurrent(): Cannot make invalid context current (%d %p %p)", d->valid, d->eglContext, d->eglImage); + if (!d->valid || !d->eglContext) { + qWarning("QGLContext::makeCurrent(): Cannot make invalid context current (%d %p)", d->valid, d->eglContext); return; } - if (d->eglContext->makeCurrent(d->eglImage)) + if (d->eglContext->makeCurrent()) QGLContextPrivate::setCurrentContext(this); } #endif @@ -263,12 +261,6 @@ void QGLContext::swapBuffers() const widget = static_cast<QWidget*>(device()); surf = widget->winId(); - if (d->eglImage == EGL_NO_IMAGE_KHR) - qFatal("bad image at swap time\n"); - visual = (struct wl_visual *)wl_display_get_premultiplied_argb_visual(qWayland->wl_display); - if (!visual) - qWarning("bad wayland visual\n"); - wl_surface_attach(surf, d->drmName, 100, 100, d->drmStride, visual); wl_surface_map(surf, 0, 0, 100, 100); wl_compositor_commit(qWayland->compositor, 10); wl_display_iterate(qWayland->wl_display, WL_DISPLAY_WRITABLE); @@ -299,10 +291,6 @@ void QGLContextPrivate::destroyEglSurfaceForDevice() #else void QGLContextPrivate::destroyEglSurfaceForDevice() { - if (eglImage != EGL_NO_IMAGE_KHR) { - QEgl::eglDestroyImageKHR(eglContext->display(), eglImage); - eglImage = EGL_NO_IMAGE_KHR; - } } #endif diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 3b809e4754..01021a5962 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -353,7 +353,6 @@ public: * have to use an EGL image and a framebuffer object for our rendering * needs */ - EGLImageKHR eglImage; EGLint drmName; EGLint drmHandle; EGLint drmStride; diff --git a/src/opengl/qgl_waylandegl.cpp b/src/opengl/qgl_waylandegl.cpp index bfa9bfcdfe..28e4e71faf 100644 --- a/src/opengl/qgl_waylandegl.cpp +++ b/src/opengl/qgl_waylandegl.cpp @@ -221,22 +221,8 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) // QPixmap - yes, create the EGLSurface but store it in QX11PixmapData::gl_surface // QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf - if (devType == QInternal::Widget) { - if (d->eglImage != EGL_NO_IMAGE_KHR) - QEgl::eglDestroyImageKHR(d->eglContext->display(), d->eglImage); - d->eglImage = QEgl::createImage(device(), d->eglContext->config()); - if (!d->eglImage) - qWarning("failed to create EGL image: 0x%08x\n", eglGetError()); - if (!QEgl::eglExportDRMImageMESA(qWayland->egl_display, d->eglImage, - &name, &handle, &stride)) { - qWarning("failed to export EGL image: 0x%08x\n", eglGetError()); - d->eglImage = EGL_NO_IMAGE_KHR; - } - d->drmName = name; - d->drmHandle = handle; - d->drmStride = stride; + if (devType == QInternal::Widget) setWindowCreated(true); - } return true; } diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 3967a09057..0454660f68 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -146,7 +146,6 @@ void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &form qctx->d_func()->vi = 0; #elif defined(Q_WS_WAYLAND) qctx->d_func()->eglContext = ctx; - qctx->d_func()->eglImage = pbuf; #elif !defined(QT_NO_EGL) qctx->d_func()->eglContext = ctx; qctx->d_func()->eglSurface = pbuf; diff --git a/src/opengl/qwindowsurface_waylandgl.cpp b/src/opengl/qwindowsurface_waylandgl.cpp index 09d5ac8817..87c77d1db1 100644 --- a/src/opengl/qwindowsurface_waylandgl.cpp +++ b/src/opengl/qwindowsurface_waylandgl.cpp @@ -62,6 +62,8 @@ #include "qwindowsurface_waylandgl_p.h" #include "qpixmapdata_waylandgl_p.h" +#include <private/qt_wayland_p.h> + QT_BEGIN_NAMESPACE class QWaylandGlobalShareWidget @@ -263,7 +265,9 @@ QPaintDevice *QWaylandWindowSurface::paintDevice() return d_ptr->fbo; } -static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &src = QRectF()); +static void drawTexture(struct QWaylandWindowSurfacePrivate *d_ptr, + const QRectF &rect, GLuint tex_id, + const QSize &texSize, const QRectF &src = QRectF()); void QWaylandWindowSurface::beginPaint(const QRegion &) { @@ -280,6 +284,9 @@ void QWaylandWindowSurface::endPaint(const QRegion &rgn) void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { + struct wl_visual *visual; + EGLint name, stride, handle; + if (context() && widget != window()) { qWarning("No native child widget support in GL window surface without FBOs or pixel buffers"); return; @@ -329,6 +336,8 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &rgn, if (ctx != previous_ctx) { ctx->makeCurrent(); + } else { + previous_ctx->makeCurrent(); } QSize size = widget->rect().size(); @@ -340,106 +349,30 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &rgn, glDisable(GL_SCISSOR_TEST); - if (d_ptr->fbo && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)) { - const int h = d_ptr->fbo->height(); - - const int sx0 = br.left(); - const int sx1 = br.left() + br.width(); - const int sy0 = h - (br.top() + br.height()); - const int sy1 = h - br.top(); - - const int tx0 = rect.left(); - const int tx1 = rect.left() + rect.width(); - const int ty0 = parent->height() - (rect.top() + rect.height()); - const int ty1 = parent->height() - rect.top(); - - if (window() == parent || d_ptr->fbo->format().samples() <= 1) { - // glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); - - glBlitFramebufferEXT(sx0, sy0, sx1, sy1, - tx0, ty0, tx1, ty1, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0); - } else { - // can't do sub-region blits with multisample FBOs - QGLFramebufferObject *temp = qgl_fbo_pool()->acquire(d_ptr->fbo->size(), QGLFramebufferObjectFormat()); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, temp->handle()); - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); - - glBlitFramebufferEXT(0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(), - 0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(), - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, temp->handle()); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); - - glBlitFramebufferEXT(sx0, sy0, sx1, sy1, - tx0, ty0, tx1, ty1, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0); - - qgl_fbo_pool()->release(temp); - } - } -#if !defined(QT_OPENGL_ES_2) - else { - GLuint texture; - if (d_ptr->fbo) { - texture = d_ptr->fbo->texture(); - } else { - d_ptr->pb->makeCurrent(); - glBindTexture(target, d_ptr->pb_tex_id); - const uint bottom = window()->height() - (br.y() + br.height()); - glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height()); - texture = d_ptr->pb_tex_id; - glBindTexture(target, 0); - } - - glDisable(GL_DEPTH_TEST); - - if (d_ptr->fbo) { - d_ptr->fbo->release(); - } else { - ctx->makeCurrent(); - } - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); -#ifndef QT_OPENGL_ES - glOrtho(0, size.width(), size.height(), 0, -999999, 999999); -#else - glOrthof(0, size.width(), size.height(), 0, -999999, 999999); -#endif - glViewport(0, 0, size.width(), size.height()); - - glColor4f(1, 1, 1, 1); - drawTexture(rect, texture, window()->size(), br); - - if (d_ptr->fbo) - d_ptr->fbo->bind(); - } -#else // OpenGL/ES 2.0 version of the fbo blit. - else if (d_ptr->fbo && 0) { + if (d_ptr->fbo) { Q_UNUSED(target); GLuint texture = d_ptr->fbo->texture(); + GLuint surf_fbo, surf_rbo; glDisable(GL_DEPTH_TEST); + /* Unbind the widget fbo and bind the Wayland surface FBO */ if (d_ptr->fbo->isBound()) d_ptr->fbo->release(); + + glGenFramebuffers(1, &surf_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, surf_fbo); + glGenRenderbuffers(1, &surf_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, surf_rbo); + QEgl::glEGLImageTargetRenderbufferStorage(GL_RENDERBUFFER, + d_ptr->eglImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, surf_rbo); + qWarning("drawing into image %p as texture\n", d_ptr->eglImage); + glViewport(0, 0, size.width(), size.height()); QGLShaderProgram *blitProgram = @@ -464,14 +397,22 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &rgn, else r.setTop((rect.bottom() / w) * 2.0f - 1.0f); - drawTexture(r, texture, window()->size(), br); + drawTexture(d_ptr, r, texture, window()->size(), br); } -#endif - if (ctx->format().doubleBuffer()) - ctx->swapBuffers(); - else - glFlush(); + if (!QEgl::eglExportDRMImageMESA(qWayland->egl_display, d_ptr->eglImage, + &name, &handle, &stride)) { + qWarning("failed to export EGL image: 0x%08x\n", eglGetError()); + } + glFinish(); + + visual = (struct wl_visual *)wl_display_get_premultiplied_argb_visual(qWayland->wl_display); + if (!visual) + qWarning("bad wayland visual\n"); + wl_surface_attach(window()->winId(), name, size.width(), size.height(), + stride, visual); + wl_surface_map(window()->winId(), 0, 0, size.width(), size.height()); + wl_compositor_commit(qWayland->compositor, 10); } void QWaylandWindowSurface::setGeometry(const QRect &rect) @@ -480,21 +421,42 @@ void QWaylandWindowSurface::setGeometry(const QRect &rect) d_ptr->geometry_updated = true; } +EGLImageKHR QWaylandWindowSurface::createImage(QRect *rect) +{ + EGLImageKHR img; + EGLint attribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_IMAGE_FORMAT_MESA, EGL_IMAGE_FORMAT_ARGB8888_MESA, + EGL_IMAGE_USE_MESA, EGL_IMAGE_USE_SHARE_MESA | + EGL_IMAGE_USE_SCANOUT_MESA, + EGL_NONE, + }; + + attribs[1] = rect->width(); + attribs[3] = rect->height(); + + img = QEgl::eglCreateDRMImageMESA(qWayland->egl_display, attribs); + if (!img) { + qWarning("failed to create EGL image: %d\n", eglGetError()); + return NULL; + } else { + qWarning("created EGL image %dx%d\n", attribs[1], attribs[3]); + } + return img; +} + void QWaylandWindowSurface::updateGeometry() { if (!d_ptr->geometry_updated) return; - d_ptr->geometry_updated = false; + d_ptr->geometry_updated = false; QRect rect = geometry(); hijackWindow(window()); QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); -#ifdef Q_WS_MAC - ctx->updatePaintDevice(); -#endif - const GLenum target = GL_TEXTURE_2D; if (rect.width() <= 0 || rect.height() <= 0) @@ -505,43 +467,34 @@ void QWaylandWindowSurface::updateGeometry() d_ptr->size = rect.size(); - if (d_ptr->ctx) { -#ifndef QT_OPENGL_ES_2 - if (d_ptr->destructive_swap_buffers) { - glBindTexture(target, d_ptr->tex_id); - glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - glBindTexture(target, 0); - } -#endif + if (d_ptr->ctx) return; - } - - if ((QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject) - && qt_gl_preferGL2Engine()) - { - ctx->d_ptr->internal_context = true; - ctx->makeCurrent(); - delete d_ptr->fbo; - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - format.setInternalTextureFormat(GLenum(GL_RGBA)); - format.setTextureTarget(target); - - if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit) - format.setSamples(8); + ctx->d_ptr->internal_context = true; + ctx->makeCurrent(); + delete d_ptr->fbo; - d_ptr->fbo = new QGLFramebufferObject(rect.size(), format); + QGLFramebufferObjectFormat format; + format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + format.setInternalTextureFormat(GLenum(GL_RGBA)); + format.setTextureTarget(target); + + d_ptr->fbo = new QGLFramebufferObject(rect.size(), format); + d_ptr->eglImage = createImage(&rect); + if (d_ptr->eglImage == EGL_NO_IMAGE_KHR) { + qWarning("failed to create egl image: 0x%08x\n", eglGetError()); + delete d_ptr->fbo; + return; + } - if (d_ptr->fbo->isValid()) { - qDebug() << "Created Window Surface FBO" << rect.size() - << "with samples" << d_ptr->fbo->format().samples(); - return; - } else { - qDebug() << "QWaylandWindowSurface: Failed to create valid FBO, falling back"; - delete d_ptr->fbo; - d_ptr->fbo = 0; - } + if (d_ptr->fbo->isValid()) { + qDebug() << "Created Window Surface FBO" << rect.size() + << "with samples" << d_ptr->fbo->format().samples(); + return; + } else { + qDebug() << "QWaylandWindowSurface: Failed to create valid FBO, falling back"; + delete d_ptr->fbo; + d_ptr->fbo = 0; } ctx->makeCurrent(); @@ -580,13 +533,16 @@ bool QWaylandWindowSurface::scroll(const QRegion &area, int dx, int dy) glCopyTexImage2D(target, 0, GL_RGBA, br.x(), d_ptr->pb->height() - (br.y() + br.height()), br.width(), br.height(), 0); glBindTexture(target, 0); - drawTexture(br.translated(dx, dy), d_ptr->tex_id, window()->size()); + drawTexture(d_ptr, br.translated(dx, dy), d_ptr->tex_id, window()->size()); return true; } -static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br) +static void drawTexture(struct QWaylandWindowSurfacePrivate *d_ptr, + const QRectF &rect, GLuint tex_id, + const QSize &texSize, const QRectF &br) { + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); const GLenum target = GL_TEXTURE_2D; QRectF src = br.isEmpty() ? QRectF(QPointF(), texSize) @@ -615,22 +571,6 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); // qpaintengine_opengl.cpp qt_add_rect_to_array(rect, vertexArray); -#if !defined(QT_OPENGL_ES_2) - glVertexPointer(2, GL_FLOAT, 0, vertexArray); - glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); - - glBindTexture(target, tex_id); - glEnable(target); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisable(target); - glBindTexture(target, 0); -#else glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); @@ -643,7 +583,6 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); glBindTexture(target, 0); -#endif } QImage *QWaylandWindowSurface::buffer(const QWidget *widget) diff --git a/src/opengl/qwindowsurface_waylandgl_p.h b/src/opengl/qwindowsurface_waylandgl_p.h index 4a6dbc924c..372032ba9a 100644 --- a/src/opengl/qwindowsurface_waylandgl_p.h +++ b/src/opengl/qwindowsurface_waylandgl_p.h @@ -57,6 +57,7 @@ #include <qgl.h> #include <private/qwindowsurface_p.h> #include <private/qglpaintdevice_p.h> +#include <private/qt_wayland_p.h> QT_BEGIN_NAMESPACE @@ -103,6 +104,7 @@ private slots: private: void hijackWindow(QWidget *widget); + EGLImageKHR createImage(QRect *rect); QWaylandWindowSurfacePrivate *d_ptr; }; |