diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-06-17 23:20:34 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-06-17 23:20:34 -0700 |
commit | a6cd1146c4144f8fa85174b97db70678af0ab939 (patch) | |
tree | c553c9c26f06fb7dc76aeb11c503322cba187d1d | |
parent | 744d2a603f1fd58270b5b0bd07208611c91ce9da (diff) |
Window surface for Wayland
-rw-r--r-- | src/gui/kernel/qwidget.h | 3 | ||||
-rw-r--r-- | src/opengl/qgl.h | 3 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer.h | 3 | ||||
-rw-r--r-- | src/opengl/qgraphicssystem_gl.cpp | 2 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_waylandgl.cpp | 609 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_waylandgl_p.h | 36 |
6 files changed, 618 insertions, 38 deletions
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 941bd68929..7a65262472 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -735,6 +735,9 @@ private: friend class QGLContext; friend class QGLWidget; friend class QGLWindowSurface; +#ifdef Q_WS_WAYLAND + friend class QWaylandWindowSurface; +#endif friend class QX11PaintEngine; friend class QWin32PaintEngine; friend class QShortcutPrivate; diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index f0b36f75ea..c700d78be3 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -414,6 +414,9 @@ private: friend class QGL2PaintEngineExPrivate; friend class QGLEngineShaderManager; friend class QGLWindowSurface; +#ifdef Q_WS_WAYLAND + friend class QWaylandWindowSurface; +#endif friend class QGLPixmapData; friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; diff --git a/src/opengl/qglpixelbuffer.h b/src/opengl/qglpixelbuffer.h index d9c7e3e5ef..0490e6be2a 100644 --- a/src/opengl/qglpixelbuffer.h +++ b/src/opengl/qglpixelbuffer.h @@ -111,6 +111,9 @@ private: friend class QGLDrawable; friend class QGLWindowSurface; friend class QGLPaintDevice; +#ifdef Q_WS_WAYLAND + friend class QWaylandWindowSurface; +#endif friend class QGLPBufferGLPaintDevice; friend class QGLContextPrivate; }; diff --git a/src/opengl/qgraphicssystem_gl.cpp b/src/opengl/qgraphicssystem_gl.cpp index afbaa7abab..cff8400823 100644 --- a/src/opengl/qgraphicssystem_gl.cpp +++ b/src/opengl/qgraphicssystem_gl.cpp @@ -91,7 +91,7 @@ QWindowSurface *QGLGraphicsSystem::createWindowSurface(QWidget *widget) const #endif #ifdef Q_WS_WAYLAND -// return new QWaylandWindowSurface(widget); + return new QWaylandWindowSurface(widget); #endif return new QGLWindowSurface(widget); diff --git a/src/opengl/qwindowsurface_waylandgl.cpp b/src/opengl/qwindowsurface_waylandgl.cpp index 1fcb457b50..09d5ac8817 100644 --- a/src/opengl/qwindowsurface_waylandgl.cpp +++ b/src/opengl/qwindowsurface_waylandgl.cpp @@ -41,80 +41,629 @@ #include <private/qimagepixmapcleanuphooks_p.h> +#include <qglframebufferobject.h> +#include <qglpixelbuffer.h> +#include <qcolormap.h> +#include <qdesktopwidget.h> +#include <private/qwidget_p.h> +#include "qdebug.h" + +#include <private/qglextensions_p.h> +#include <private/qwindowsurface_gl_p.h> + +#include <private/qgl_p.h> + +#include <private/qglpixelbuffer_p.h> +#include <private/qgraphicssystem_gl_p.h> + +#include <private/qpaintengineex_opengl2_p.h> +#include <private/qpixmapdata_gl_p.h> + #include "qwindowsurface_waylandgl_p.h" #include "qpixmapdata_waylandgl_p.h" QT_BEGIN_NAMESPACE +class QWaylandGlobalShareWidget +{ +public: + QWaylandGlobalShareWidget() : widget(0), initializing(false) {} + + QGLWidget *shareWidget() { + if (!initializing && !widget && !cleanedUp) { + initializing = true; + widget = new QGLWidget; + // We dont need this internal widget to appear in QApplication::topLevelWidgets() + if (QWidgetPrivate::allWidgets) + QWidgetPrivate::allWidgets->remove(widget); + initializing = false; + } + return widget; + } + + void cleanup() { + QGLWidget *w = widget; + cleanedUp = true; + widget = 0; + delete w; + } + + static bool cleanedUp; + +private: + QGLWidget *widget; + bool initializing; +}; + +bool QWaylandGlobalShareWidget::cleanedUp = false; + +static void qt_cleanup_gl_share_widget(); +Q_GLOBAL_STATIC_WITH_INITIALIZER(QWaylandGlobalShareWidget, _qt_wayland_gl_share_widget, + { + qAddPostRoutine(qt_cleanup_gl_share_widget); + }) + +static void qt_cleanup_gl_share_widget() +{ + _qt_wayland_gl_share_widget()->cleanup(); +} + +QGLWidget* qt_wayland_gl_share_widget() +{ + if (QWaylandGlobalShareWidget::cleanedUp) + return 0; + return _qt_wayland_gl_share_widget()->shareWidget(); +} + +struct QWaylandWindowSurfacePrivate +{ + EGLImageKHR eglImage; + QGLFramebufferObject *fbo; + QGLPixelBuffer *pb; + GLuint tex_id; + GLuint pb_tex_id; + + int geometry_updated : 1; + + QGLContext *ctx; + + QList<QGLContext **> contexts; + + QRegion paintedRegion; + QSize size; + + QList<QImage> buffers; + QWaylandWindowSurfaceGLPaintDevice glDevice; + QWaylandWindowSurface* q_ptr; +}; + +QGLFormat QWaylandWindowSurface::surfaceFormat; + +void QWaylandWindowSurfaceGLPaintDevice::endPaint() +{ + glFlush(); + QGLPaintDevice::endPaint(); +} + +QSize QWaylandWindowSurfaceGLPaintDevice::size() const +{ + return d->size; +} + +QGLContext* QWaylandWindowSurfaceGLPaintDevice::context() const +{ + return d->ctx; +} + + +int QWaylandWindowSurfaceGLPaintDevice::metric(PaintDeviceMetric m) const +{ + return qt_paint_device_metric(d->q_ptr->window(), m); +} + +QPaintEngine *QWaylandWindowSurfaceGLPaintDevice::paintEngine() const +{ + return qt_qgl_paint_engine(); +} + QWaylandWindowSurface::QWaylandWindowSurface(QWidget* window) - : QWindowSurface(window), m_window(window) + : QWindowSurface(window), d_ptr(new QWaylandWindowSurfacePrivate) { + Q_ASSERT(window->isTopLevel()); + + d_ptr->pb = 0; + d_ptr->fbo = 0; + d_ptr->ctx = 0; + + d_ptr->glDevice.d = d_ptr; + d_ptr->q_ptr = this; + d_ptr->geometry_updated = false; } QWaylandWindowSurface::~QWaylandWindowSurface() { + if (d_ptr->ctx) + glDeleteTextures(1, &d_ptr->tex_id); + foreach(QGLContext **ctx, d_ptr->contexts) { + delete *ctx; + *ctx = 0; + } + + delete d_ptr->pb; + delete d_ptr->fbo; + delete d_ptr; +} + +void QWaylandWindowSurface::deleted(QObject *object) +{ + // Make sure that the fbo is destroyed before destroying its context. + delete d_ptr->fbo; + d_ptr->fbo = 0; + + QWidget *widget = qobject_cast<QWidget *>(object); + if (widget) { + QWidgetPrivate *widgetPrivate = widget->d_func(); + if (widgetPrivate->extraData()) { + union { QGLContext **ctxPtr; void **voidPtr; }; + voidPtr = &widgetPrivate->extraData()->glContext; + int index = d_ptr->contexts.indexOf(ctxPtr); + if (index != -1) { + delete *ctxPtr; + *ctxPtr = 0; + d_ptr->contexts.removeAt(index); + } + } + } +} + +void QWaylandWindowSurface::hijackWindow(QWidget *widget) +{ + QWidgetPrivate *widgetPrivate = widget->d_func(); + widgetPrivate->createExtra(); + if (widgetPrivate->extraData()->glContext) + return; + + QGLContext *ctx = new QGLContext(surfaceFormat, widget); + ctx->create(qt_wayland_gl_share_widget()->context()); + +#ifndef QT_NO_EGL + if (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) != EGL_BUFFER_PRESERVED) + setPartialUpdateSupport(false); // Force full-screen updates +#endif + + widgetPrivate->extraData()->glContext = ctx; + + union { QGLContext **ctxPtr; void **voidPtr; }; + + connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(deleted(QObject*))); + + voidPtr = &widgetPrivate->extraData()->glContext; + d_ptr->contexts << ctxPtr; + qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size(); +} + +QGLContext *QWaylandWindowSurface::context() const +{ + return d_ptr->ctx; } QPaintDevice *QWaylandWindowSurface::paintDevice() { - return &m_backBuffer; + updateGeometry(); + + if (d_ptr->pb) + return d_ptr->pb; + + if (d_ptr->ctx) + return &d_ptr->glDevice; + + QGLContext *ctx = reinterpret_cast<QGLContext *> + (window()->d_func()->extraData()->glContext); + ctx->makeCurrent(); + return d_ptr->fbo; +} + +static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &src = QRectF()); + +void QWaylandWindowSurface::beginPaint(const QRegion &) +{ } -void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, +void QWaylandWindowSurface::endPaint(const QRegion &rgn) +{ + if (context()) + d_ptr->paintedRegion |= rgn; + + d_ptr->buffers.clear(); +} + +void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { - eglWaitNative(EGL_CORE_NATIVE_ENGINE); + if (context() && widget != window()) { + qWarning("No native child widget support in GL window surface without FBOs or pixel buffers"); + return; + } + + //### Find out why d_ptr->geometry_updated isn't always false. + // flush() should not be called when d_ptr->geometry_updated is true. It assumes that either + // d_ptr->fbo or d_ptr->pb is allocated and has the correct size. + if (d_ptr->geometry_updated) + return; + + QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); + Q_ASSERT(parent); + + if (!geometry().isValid()) + return; + + // Needed to support native child-widgets... + hijackWindow(parent); + + QRect br = rgn.boundingRect().translated(offset); + br = br.intersected(window()->rect()); + QPoint wOffset = qt_qwidget_data(parent)->wrect.topLeft(); + QRect rect = br.translated(-offset - wOffset); + + const GLenum target = GL_TEXTURE_2D; + Q_UNUSED(target); + + if (context()) { + context()->makeCurrent(); + + if (context()->format().doubleBuffer()) { + d_ptr->paintedRegion = QRegion(); + context()->swapBuffers(); + } else { + glFlush(); + } + + return; + } + + QGLContext *previous_ctx = const_cast<QGLContext *>(QGLContext::currentContext()); + QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext); + + // QPainter::end() should have unbound the fbo, otherwise something is very wrong... + Q_ASSERT(!d_ptr->fbo || !d_ptr->fbo->isBound()); + + if (ctx != previous_ctx) { + ctx->makeCurrent(); + } + + QSize size = widget->rect().size(); + if (ctx->format().doubleBuffer()) { + rect = parent->rect(); + br = rect.translated(wOffset + offset); + size = parent->size(); + } + + 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) { + Q_UNUSED(target); + + GLuint texture = d_ptr->fbo->texture(); + + glDisable(GL_DEPTH_TEST); + + if (d_ptr->fbo->isBound()) + d_ptr->fbo->release(); + + glViewport(0, 0, size.width(), size.height()); + + QGLShaderProgram *blitProgram = + QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram(); + blitProgram->bind(); + blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); + + // The shader manager's blit program does not multiply the + // vertices by the pmv matrix, so we need to do the effect + // of the orthographic projection here ourselves. + QRectF r; + qreal w = size.width() ? size.width() : 1.0f; + qreal h = size.height() ? size.height() : 1.0f; + r.setLeft((rect.left() / w) * 2.0f - 1.0f); + if (rect.right() == (size.width() - 1)) + r.setRight(1.0f); + else + r.setRight((rect.right() / w) * 2.0f - 1.0f); + r.setBottom((rect.top() / h) * 2.0f - 1.0f); + if (rect.bottom() == (size.height() - 1)) + r.setTop(1.0f); + else + r.setTop((rect.bottom() / w) * 2.0f - 1.0f); + + drawTexture(r, texture, window()->size(), br); + } +#endif + + if (ctx->format().doubleBuffer()) + ctx->swapBuffers(); + else + glFlush(); } void QWaylandWindowSurface::setGeometry(const QRect &rect) { - if (rect.width() > m_backBuffer.size().width() || - rect.height() > m_backBuffer.size().height()) { - QWaylandGLPixmapData *pd = new QWaylandGLPixmapData; - QSize newSize = rect.size(); - pd->resize(newSize.width(), newSize.height()); - m_backBuffer = QPixmap(pd); - if (window()->testAttribute(Qt::WA_TranslucentBackground)) - m_backBuffer.fill(Qt::transparent); - } QWindowSurface::setGeometry(rect); + d_ptr->geometry_updated = true; } void QWaylandWindowSurface::updateGeometry() { + if (!d_ptr->geometry_updated) + return; + 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) + return; + + if (d_ptr->size == rect.size()) + return; + + 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 + 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); + + d_ptr->fbo = new QGLFramebufferObject(rect.size(), format); + + 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(); + + qDebug() << "QWaylandWindowSurface: Using plain widget as window surface" << this;; + d_ptr->ctx = ctx; + d_ptr->ctx->d_ptr->internal_context = true; } bool QWaylandWindowSurface::scroll(const QRegion &area, int dx, int dy) { - eglWaitNative(EGL_CORE_NATIVE_ENGINE); + // this code randomly fails currently for unknown reasons + return false; + + if (!d_ptr->pb) + return false; + + d_ptr->pb->makeCurrent(); + + QRect br = area.boundingRect(); + +#if 0 + // ## workaround driver issue (scrolling by these deltas is unbearably slow for some reason) + // ## maybe we should use glCopyTexSubImage insteadk + if (dx == 1 || dx == -1 || dy == 1 || dy == -1 || dy == 2) + return false; + glRasterPos2i(br.x() + dx, br.y() + br.height() + dy); + glCopyPixels(br.x(), d_ptr->pb->height() - (br.y() + br.height()), br.width(), br.height(), GL_COLOR); return true; -} +#endif -void QWaylandWindowSurface::beginPaint(const QRegion ®ion) -{ + const GLenum target = GL_TEXTURE_2D; + + glBindTexture(target, d_ptr->tex_id); + 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()); + + return true; } -void QWaylandWindowSurface::endPaint(const QRegion ®ion) +static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br) { -#if 0 - struct wl_visual *visual; - EGLint name, stride; - - QEgl::eglExportDRMImageMESA(qWayland->egl_display, image, &name, NULL, - &stride); - visual = wl_display_get_premultiplied_argb_visual(qWayland->egl_display); - wl_surface_attach(surface, name, width, height, stride, visual); - wl_surface_map(surface, 0, 0, width, height); + const GLenum target = GL_TEXTURE_2D; + QRectF src = br.isEmpty() + ? QRectF(QPointF(), texSize) + : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); + + if (target == GL_TEXTURE_2D) { + qreal width = texSize.width(); + qreal height = texSize.height(); + + src.setLeft(src.left() / width); + src.setRight(src.right() / width); + src.setTop(src.top() / height); + src.setBottom(src.bottom() / height); + } + + const GLfloat tx1 = src.left(); + const GLfloat tx2 = src.right(); + const GLfloat ty1 = src.top(); + const GLfloat ty2 = src.bottom(); + + GLfloat texCoordArray[4*2] = { + tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 + }; + + GLfloat vertexArray[4*2]; + 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); + + glBindTexture(target, tex_id); + + glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + + glBindTexture(target, 0); #endif } QImage *QWaylandWindowSurface::buffer(const QWidget *widget) { -} + QImage image; -QGLContext *QWaylandWindowSurface::context() const -{ + if (d_ptr->pb) + image = d_ptr->pb->toImage(); + else if (d_ptr->fbo) + image = d_ptr->fbo->toImage(); + + if (image.isNull()) + return 0; + + QRect rect = widget->rect(); + rect.translate(widget->mapTo(widget->window(), QPoint())); + + QImage subImage = image.copy(rect); + d_ptr->buffers << subImage; + return &d_ptr->buffers.last(); } QT_END_NAMESPACE diff --git a/src/opengl/qwindowsurface_waylandgl_p.h b/src/opengl/qwindowsurface_waylandgl_p.h index d287b7c9d8..4a6dbc924c 100644 --- a/src/opengl/qwindowsurface_waylandgl_p.h +++ b/src/opengl/qwindowsurface_waylandgl_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QWINDOWSURFACE_X11GL_P_H -#define QWINDOWSURFACE_X11GL_P_H +#ifndef QWINDOWSURFACE_WAYLANDGL_P_H +#define QWINDOWSURFACE_WAYLANDGL_P_H // // W A R N I N G @@ -60,13 +60,30 @@ QT_BEGIN_NAMESPACE -class QWaylandWindowSurface : public QWindowSurface +class QPaintDevice; +class QPoint; +class QRegion; +class QWidget; +struct QWaylandWindowSurfacePrivate; + +class QWaylandWindowSurfaceGLPaintDevice : public QGLPaintDevice { public: + QPaintEngine* paintEngine() const; + void endPaint(); + QSize size() const; + int metric(PaintDeviceMetric m) const; + QGLContext* context() const; + QWaylandWindowSurfacePrivate* d; +}; + +class QWaylandWindowSurface : public QObject, public QWindowSurface +{ + Q_OBJECT +public: QWaylandWindowSurface(QWidget* window); virtual ~QWaylandWindowSurface(); - // Inherreted from QWindowSurface QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); void setGeometry(const QRect &rect); @@ -80,12 +97,17 @@ public: QGLContext *context() const; + static QGLFormat surfaceFormat; +private slots: + void deleted(QObject *object); + private: - QWidget *m_window; - QPixmap m_backBuffer; + void hijackWindow(QWidget *widget); + + QWaylandWindowSurfacePrivate *d_ptr; }; QT_END_NAMESPACE -#endif // QWINDOWSURFACE_X11GL_P_H +#endif // QWINDOWSURFACE_WAYLANDGL_P_H |