From ff11af4fbc2948a3a3bc635549c7ac349d249abc Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 11 Feb 2014 14:59:30 +0100 Subject: QOpenGLWidget and new-style compositing on eglfs Integrate with QOpenGLTextureBlitter, QOpenGLWidget and friends. Change-Id: Ic2867b713a21a3d2820d546174fc9164b3dd220c Reviewed-by: Lars Knoll Reviewed-by: Gunnar Sletta Reviewed-by: Paul Olav Tvete --- src/gui/painting/qplatformbackingstore.cpp | 6 + src/gui/painting/qplatformbackingstore.h | 2 + .../eglconvenience/qeglcompositor.cpp | 134 +++++++-------------- .../eglconvenience/qeglcompositor_p.h | 10 +- .../eglconvenience/qeglplatformbackingstore.cpp | 100 +++++++++++---- .../eglconvenience/qeglplatformbackingstore_p.h | 22 +++- .../eglconvenience/qeglplatformcontext.cpp | 17 +-- .../eglconvenience/qeglplatformintegration.cpp | 22 +++- .../eglconvenience/qeglplatformintegration_p.h | 10 ++ .../eglconvenience/qeglplatformwindow.cpp | 18 ++- .../eglconvenience/qeglplatformwindow_p.h | 6 +- src/plugins/platforms/eglfs/eglfs.pri | 2 - src/plugins/platforms/eglfs/qeglfsintegration.cpp | 25 ++-- src/plugins/platforms/eglfs/qeglfsintegration.h | 9 +- src/plugins/platforms/eglfs/qeglfsscreen.cpp | 4 - src/plugins/platforms/eglfs/qeglfswindow.cpp | 6 +- src/widgets/kernel/qwidgetbackingstore.cpp | 35 +++++- src/widgets/kernel/qwidgetbackingstore_p.h | 20 +++ .../qopenglwidget/openglwidget/openglwidget.cpp | 2 - 19 files changed, 275 insertions(+), 175 deletions(-) diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index d2b1f056d7..a77fbb6826 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -156,6 +156,12 @@ void QPlatformTextureList::appendTexture(GLuint textureId, const QRect &geometry bi.rect = geometry; d->textures.append(bi); } + +void QPlatformTextureList::clear() +{ + Q_D(QPlatformTextureList); + d->textures.clear(); +} #endif // QT_NO_OPENGL /*! diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h index a662a2290b..76fd3d40b4 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -81,12 +81,14 @@ public: ~QPlatformTextureList(); int count() const; + bool isEmpty() const { return count() == 0; } GLuint textureId(int index) const; QRect geometry(int index) const; void lock(bool on); bool isLocked() const; void appendTexture(GLuint textureId, const QRect &geometry); + void clear(); Q_SIGNALS: void locked(bool); diff --git a/src/platformsupport/eglconvenience/qeglcompositor.cpp b/src/platformsupport/eglconvenience/qeglcompositor.cpp index f81d72c4bd..aac4822f66 100644 --- a/src/platformsupport/eglconvenience/qeglcompositor.cpp +++ b/src/platformsupport/eglconvenience/qeglcompositor.cpp @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include "qeglcompositor_p.h" #include "qeglplatformwindow_p.h" @@ -54,7 +56,7 @@ static QEGLCompositor *compositor = 0; QEGLCompositor::QEGLCompositor() : m_context(0), m_window(0), - m_program(0) + m_blitter(0) { Q_ASSERT(!compositor); m_updateTimer.setSingleShot(true); @@ -65,7 +67,10 @@ QEGLCompositor::QEGLCompositor() QEGLCompositor::~QEGLCompositor() { Q_ASSERT(compositor == this); - delete m_program; + if (m_blitter) { + m_blitter->destroy(); + delete m_blitter; + } compositor = 0; } @@ -81,102 +86,53 @@ void QEGLCompositor::renderAll() { Q_ASSERT(m_context && m_window); m_context->makeCurrent(m_window->window()); - ensureProgram(); - m_program->bind(); + + if (!m_blitter) { + m_blitter = new QOpenGLTextureBlitter; + m_blitter->create(); + } + m_blitter->bind(); QEGLPlatformScreen *screen = static_cast(m_window->screen()); QList windows = screen->windows(); - for (int i = 0; i < windows.size(); ++i) { - QEGLPlatformWindow *window = windows.at(i); - uint texture = window->texture(); - if (texture) - render(window, texture, window->isRaster()); - } + for (int i = 0; i < windows.size(); ++i) + render(windows.at(i)); - m_program->release(); + m_blitter->release(); m_context->swapBuffers(m_window->window()); -} -void QEGLCompositor::ensureProgram() -{ - if (!m_program) { - static const char *textureVertexProgram = - "attribute highp vec2 vertexCoordEntry;\n" - "attribute highp vec2 textureCoordEntry;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " textureCoord = textureCoordEntry;\n" - " gl_Position = vec4(vertexCoordEntry, 0.0, 1.0);\n" - "}\n"; - - static const char *textureFragmentProgram = - "uniform sampler2D texture;\n" - "varying highp vec2 textureCoord;\n" - "uniform bool isRaster;\n" - "void main() {\n" - " lowp vec4 c = texture2D(texture, textureCoord);\n" - " gl_FragColor = isRaster ? c.bgra : c.rgba;\n" - "}\n"; - - m_program = new QOpenGLShaderProgram; - - m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - m_program->link(); - - m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry"); - m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry"); - m_isRasterEntry = m_program->uniformLocation("isRaster"); - } + for (int i = 0; i < windows.size(); ++i) + windows.at(i)->composited(); } -void QEGLCompositor::render(QEGLPlatformWindow *window, uint texture, bool raster) +void QEGLCompositor::render(QEGLPlatformWindow *window) { - const GLfloat textureCoordinates[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - - QRectF sr = window->screen()->geometry(); - QRect r = window->window()->geometry(); - QPoint tl = r.topLeft(); - QPoint br = r.bottomRight(); - - // Map to [-1,1] - GLfloat x1 = (tl.x() / sr.width()) * 2 - 1; - GLfloat y1 = ((sr.height() - tl.y()) / sr.height()) * 2 - 1; - GLfloat x2 = ((br.x() + 1) / sr.width()) * 2 - 1; - GLfloat y2 = ((sr.height() - (br.y() + 1)) / sr.height()) * 2 - 1; - - if (!raster) - qSwap(y1, y2); - - const GLfloat vertexCoordinates[] = { - x1, y1, - x2, y1, - x2, y2, - x1, y2 - }; - - glViewport(0, 0, sr.width(), sr.height()); - - m_program->enableAttributeArray(m_vertexCoordEntry); - m_program->enableAttributeArray(m_textureCoordEntry); - - m_program->setAttributeArray(m_vertexCoordEntry, vertexCoordinates, 2); - m_program->setAttributeArray(m_textureCoordEntry, textureCoordinates, 2); - - glBindTexture(GL_TEXTURE_2D, texture); - - m_program->setUniformValue(m_isRasterEntry, raster); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBindTexture(GL_TEXTURE_2D, 0); - m_program->enableAttributeArray(m_textureCoordEntry); - m_program->enableAttributeArray(m_vertexCoordEntry); + const QPlatformTextureList *textures = window->textures(); + if (!textures) + return; + + const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size()); + glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height()); + + for (int i = 0; i < textures->count(); ++i) { + uint textureId = textures->textureId(i); + glBindTexture(GL_TEXTURE_2D, textureId); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), + targetWindowRect, + QOpenGLTextureBlitter::OriginTopLeft); + m_blitter->setSwizzleRB(window->isRaster()); + + if (textures->count() > 1 && i == textures->count() - 1) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); + glDisable(GL_BLEND); + } else if (textures->count() == 1) { + m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); + } else { + m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft); + } + } } QEGLCompositor *QEGLCompositor::instance() diff --git a/src/platformsupport/eglconvenience/qeglcompositor_p.h b/src/platformsupport/eglconvenience/qeglcompositor_p.h index 28e770e408..370345ada6 100644 --- a/src/platformsupport/eglconvenience/qeglcompositor_p.h +++ b/src/platformsupport/eglconvenience/qeglcompositor_p.h @@ -46,8 +46,8 @@ QT_BEGIN_NAMESPACE -class QOpenGLShaderProgram; class QOpenGLContext; +class QOpenGLTextureBlitter; class QEGLPlatformWindow; class QEGLCompositor : public QObject @@ -67,16 +67,12 @@ private: QEGLCompositor(); ~QEGLCompositor(); - void render(QEGLPlatformWindow *window, uint texture, bool raster); - void ensureProgram(); + void render(QEGLPlatformWindow *window); QOpenGLContext *m_context; QEGLPlatformWindow *m_window; QTimer m_updateTimer; - QOpenGLShaderProgram *m_program; - int m_vertexCoordEntry; - int m_textureCoordEntry; - int m_isRasterEntry; + QOpenGLTextureBlitter *m_blitter; }; QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp index 6a22c01a83..24e9ccd39f 100644 --- a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp @@ -76,11 +76,18 @@ QT_BEGIN_NAMESPACE QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window) : QPlatformBackingStore(window), m_window(static_cast(window->handle())), - m_texture(0) + m_bsTexture(0), + m_textures(new QPlatformTextureList), + m_lockedWidgetTextures(0) { m_window->setBackingStore(this); } +QEGLPlatformBackingStore::~QEGLPlatformBackingStore() +{ + delete m_textures; +} + QPaintDevice *QEGLPlatformBackingStore::paintDevice() { return &m_image; @@ -88,7 +95,18 @@ QPaintDevice *QEGLPlatformBackingStore::paintDevice() void QEGLPlatformBackingStore::updateTexture() { - glBindTexture(GL_TEXTURE_2D, m_texture); + if (!m_bsTexture) { + glGenTextures(1, &m_bsTexture); + glBindTexture(GL_TEXTURE_2D, m_bsTexture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // QOpenGLTextureBlitter requires GL_REPEAT for the time being + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } else { + glBindTexture(GL_TEXTURE_2D, m_bsTexture); + } if (!m_dirty.isNull()) { QRegion fixed; @@ -126,24 +144,56 @@ void QEGLPlatformBackingStore::updateTexture() void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { - Q_UNUSED(window); + // Called for ordinary raster windows. This is rare since RasterGLSurface + // support is claimed which leads to having all QWidget windows marked as + // RasterGLSurface instead of just Raster. These go through + // compositeAndFlush() instead of this function. + Q_UNUSED(region); Q_UNUSED(offset); -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglBackingStore::flush %p", window); -#endif + QEGLPlatformScreen *screen = static_cast(m_window->screen()); + QEGLPlatformWindow *dstWin = screen->compositingWindow(); + if (!dstWin || !dstWin->isRaster()) + return; + + screen->compositingContext()->makeCurrent(dstWin->window()); + updateTexture(); + m_textures->clear(); + m_textures->appendTexture(m_bsTexture, window->geometry()); + composite(screen->compositingContext(), dstWin); +} + +void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, QOpenGLContext *context) +{ + // QOpenGLWidget content provided as textures. The raster content should go on top. + + Q_UNUSED(region); + Q_UNUSED(offset); + Q_UNUSED(context); QEGLPlatformScreen *screen = static_cast(m_window->screen()); QEGLPlatformWindow *dstWin = screen->compositingWindow(); if (!dstWin || !dstWin->isRaster()) return; - m_window->create(); - QOpenGLContext *context = screen->compositingContext(); - context->makeCurrent(dstWin->window()); + screen->compositingContext()->makeCurrent(dstWin->window()); + + m_textures->clear(); + for (int i = 0; i < textures->count(); ++i) { + uint textureId = textures->textureId(i); + QRect geom = textures->geometry(i); + m_textures->appendTexture(textureId, geom); + } + updateTexture(); - composite(context, dstWin); + m_textures->appendTexture(m_bsTexture, window->geometry()); + + textures->lock(true); + m_lockedWidgetTextures = textures; + + composite(screen->compositingContext(), dstWin); } void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWindow *window) @@ -151,6 +201,15 @@ void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWi QEGLCompositor::instance()->schedule(context, window); } +void QEGLPlatformBackingStore::composited() +{ + if (m_lockedWidgetTextures) { + QPlatformTextureList *textureList = m_lockedWidgetTextures; + m_lockedWidgetTextures = 0; // may reenter so null before unlocking + textureList->lock(false); + } +} + void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn) { m_dirty |= rgn; @@ -162,25 +221,22 @@ void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticCo QEGLPlatformScreen *screen = static_cast(m_window->screen()); QEGLPlatformWindow *dstWin = screen->compositingWindow(); - if (!dstWin || !dstWin->isRaster()) + if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface)) return; m_image = QImage(size, QImage::Format_RGB32); m_window->create(); screen->compositingContext()->makeCurrent(dstWin->window()); + if (m_bsTexture) { + glDeleteTextures(1, &m_bsTexture); + m_bsTexture = 0; + } +} - if (m_texture) - glDeleteTextures(1, &m_texture); - - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); +QImage QEGLPlatformBackingStore::toImage() const +{ + return m_image; } QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h index 58fc386892..cb1e5999b0 100644 --- a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h @@ -50,31 +50,41 @@ QT_BEGIN_NAMESPACE class QOpenGLContext; +class QPlatformTextureList; class QEGLPlatformWindow; class QEGLPlatformBackingStore : public QPlatformBackingStore { public: QEGLPlatformBackingStore(QWindow *window); + ~QEGLPlatformBackingStore(); - QPaintDevice *paintDevice(); + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - void beginPaint(const QRegion &); + void beginPaint(const QRegion &) Q_DECL_OVERRIDE; - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size, const QRegion &staticContents); + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; - uint texture() const { return m_texture; } + QImage toImage() const Q_DECL_OVERRIDE; + void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, QOpenGLContext *context) Q_DECL_OVERRIDE; + + const QPlatformTextureList *textures() const { return m_textures; } virtual void composite(QOpenGLContext *context, QEGLPlatformWindow *window); + void composited(); + private: void updateTexture(); QEGLPlatformWindow *m_window; QImage m_image; - uint m_texture; QRegion m_dirty; + uint m_bsTexture; + QPlatformTextureList *m_textures; + QPlatformTextureList *m_lockedWidgetTextures; }; QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 614d086178..37875b1e2b 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -127,11 +127,8 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) { - Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Q_ASSERT(surface->surface()->supportsOpenGL()); -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::makeCurrent: %p\n",this); -#endif bindApi(m_format); EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); @@ -192,9 +189,6 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) QEGLPlatformContext::~QEGLPlatformContext() { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::~QEglContext(): %p\n",this); -#endif if (m_eglContext != EGL_NO_CONTEXT) { eglDestroyContext(m_eglDisplay, m_eglContext); m_eglContext = EGL_NO_CONTEXT; @@ -203,9 +197,6 @@ QEGLPlatformContext::~QEGLPlatformContext() void QEGLPlatformContext::doneCurrent() { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::doneCurrent:%p\n",this); -#endif bindApi(m_format); bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ok) @@ -214,9 +205,6 @@ void QEGLPlatformContext::doneCurrent() void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface) { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::swapBuffers:%p\n",this); -#endif bindApi(m_format); EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); bool ok = eglSwapBuffers(m_eglDisplay, eglSurface); @@ -226,9 +214,6 @@ void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface) void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) () { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::getProcAddress%p\n",this); -#endif bindApi(m_format); return eglGetProcAddress(procName.constData()); } diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp index 5fc1721f6c..a961035e22 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -79,8 +80,7 @@ QT_BEGIN_NAMESPACE The backing store, native interface accessors, font database, basic capability flags, etc. are provided out of the box, no - further customization is needed. Subclasses are still responsible - however for context and offscreen surface creation. + further customization is needed. \note It is critical that this class' implementation of initialize() is called. Therefore subclasses should either avoid @@ -155,6 +155,23 @@ QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window) return w; } +QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + QEGLPlatformScreen *screen = static_cast(context->screen()->handle()); + // If there is a "root" window into which raster and QOpenGLWidget content is + // composited, all other contexts must share with its context. + QOpenGLContext *compositingContext = screen ? screen->compositingContext() : 0; + return createContext(context->format(), + compositingContext ? compositingContext->handle() : context->shareHandle(), + display()); +} + +QPlatformOffscreenSurface *QEGLPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + QEGLPlatformScreen *screen = static_cast(surface->screen()->handle()); + return createOffscreenSurface(screen->display(), surface->requestedFormat(), surface); +} + bool QEGLPlatformIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { @@ -162,6 +179,7 @@ bool QEGLPlatformIntegration::hasCapability(QPlatformIntegration::Capability cap case OpenGL: return true; case ThreadedOpenGL: return true; case WindowManagement: return false; + case RasterGLSurface: return true; default: return QPlatformIntegration::hasCapability(cap); } } diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h index d3c3f07aff..f665455383 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE class QEGLPlatformScreen; class QEGLPlatformWindow; +class QEGLPlatformContext; class QFbVtHandler; class QEGLPlatformIntegration : public QPlatformIntegration, public QPlatformNativeInterface @@ -70,6 +71,8 @@ public: QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; @@ -83,6 +86,13 @@ public: protected: virtual QEGLPlatformScreen *createScreen() const = 0; virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0; + virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format, + QPlatformOpenGLContext *shareContext, + EGLDisplay display) const = 0; + virtual QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display, + const QSurfaceFormat &format, + QOffscreenSurface *surface) const = 0; + virtual EGLNativeDisplayType nativeDisplay() const { return EGL_DEFAULT_DISPLAY; } void createInputHandlers(); diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp index a635bfff29..e9b79512ba 100644 --- a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp @@ -92,7 +92,8 @@ void QEGLPlatformWindow::create() // Save the original surface type before changing to OpenGLSurface. m_raster = (window()->surfaceType() == QSurface::RasterSurface); - window()->setSurfaceType(QSurface::OpenGLSurface); + if (m_raster) // change to OpenGL, but not for RasterGLSurface + window()->setSurfaceType(QSurface::OpenGLSurface); if (window()->type() == Qt::Desktop) { QRect fullscreenRect(QPoint(), screen()->availableGeometry().size()); @@ -102,14 +103,25 @@ void QEGLPlatformWindow::create() } } -uint QEGLPlatformWindow::texture() const +bool QEGLPlatformWindow::isRaster() const +{ + return m_raster || window()->surfaceType() == QSurface::RasterGLSurface; +} + +const QPlatformTextureList *QEGLPlatformWindow::textures() const { if (m_backingStore) - return m_backingStore->texture(); + return m_backingStore->textures(); return 0; } +void QEGLPlatformWindow::composited() +{ + if (m_backingStore) + m_backingStore->composited(); +} + WId QEGLPlatformWindow::winId() const { return m_winId; diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h index 770c741623..17a1d07a79 100644 --- a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE class QEGLPlatformBackingStore; +class QPlatformTextureList; class QEGLPlatformWindow : public QPlatformWindow { @@ -58,8 +59,9 @@ public: QEGLPlatformBackingStore *backingStore() { return m_backingStore; } void setBackingStore(QEGLPlatformBackingStore *backingStore) { m_backingStore = backingStore; } - uint texture() const; - bool isRaster() const { return m_raster; } + const QPlatformTextureList *textures() const; + void composited(); + bool isRaster() const; WId winId() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri index 7afa9c9e11..6e3ba54b97 100644 --- a/src/plugins/platforms/eglfs/eglfs.pri +++ b/src/plugins/platforms/eglfs/eglfs.pri @@ -1,7 +1,5 @@ QT += core-private gui-private platformsupport-private -#DEFINES += QEGL_EXTRA_DEBUG - # Avoid X11 header collision DEFINES += MESA_EGL_NO_X11_HEADERS diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 472e58cc72..2941806f17 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -88,17 +88,6 @@ bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) cons return QEGLPlatformIntegration::hasCapability(cap); } -QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const -{ - return new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(context->format()), context->shareHandle(), display()); -} - -QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const -{ - QEglFSScreen *screen = static_cast(surface->screen()->handle()); - return new QEGLPbuffer(screen->display(), QEglFSHooks::hooks()->surfaceFormatFor(surface->requestedFormat()), surface); -} - void QEglFSIntegration::initialize() { QEglFSHooks::hooks()->platformInit(); @@ -124,6 +113,20 @@ QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const return new QEglFSWindow(window); } +QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &format, + QPlatformOpenGLContext *shareContext, + EGLDisplay display) const +{ + return new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display); +} + +QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay display, + const QSurfaceFormat &format, + QOffscreenSurface *surface) const +{ + return new QEGLPbuffer(display, QEglFSHooks::hooks()->surfaceFormatFor(format), surface); +} + QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const { switch (hint) diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index 9ff5bd6f3b..99dda1ea96 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -54,9 +54,6 @@ public: QEglFSIntegration(); ~QEglFSIntegration(); - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; - QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; - void initialize() Q_DECL_OVERRIDE; bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; @@ -67,6 +64,12 @@ public: protected: QEGLPlatformScreen *createScreen() const Q_DECL_OVERRIDE; QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; + QEGLPlatformContext *createContext(const QSurfaceFormat &format, + QPlatformOpenGLContext *shareContext, + EGLDisplay display) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display, + const QSurfaceFormat &format, + QOffscreenSurface *surface) const Q_DECL_OVERRIDE; EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE; private: diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index 11c1160ce9..31f6ac5be6 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -53,10 +53,6 @@ QEglFSScreen::QEglFSScreen(EGLDisplay dpy) m_rootWindow(0), m_rootContext(0) { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglScreen %p\n", this); -#endif - m_cursor = QEglFSHooks::hooks()->createCursor(this); } diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 279e7bbc91..2d36c0b58e 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -58,9 +58,6 @@ QEglFSWindow::QEglFSWindow(QWindow *w) , m_window(0) , m_flags(0) { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_window)); -#endif } QEglFSWindow::~QEglFSWindow() @@ -114,7 +111,8 @@ void QEglFSWindow::create() QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance()); context->setFormat(window()->requestedFormat()); context->setScreen(window()->screen()); - context->create(); + if (!context->create()) + qFatal("EGLFS: Failed to create compositing context"); screen->setRootContext(context); screen->setRootWindow(this); } diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index c8d5440999..dc918657b4 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -736,7 +736,8 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) dirtyOnScreenWidgets(0), widgetTextures(0), fullUpdatePending(0), - updateRequestSent(0) + updateRequestSent(0), + textureListWatcher(0) { store = tlw->backingStore(); Q_ASSERT(store); @@ -962,6 +963,25 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo } #endif +QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore) + : m_locked(false), + m_backingStore(backingStore) +{ +} + +void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList) +{ + connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool))); + m_locked = textureList->isLocked(); +} + +void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) +{ + m_locked = locked; + if (!locked) + m_backingStore->sync(); +} + /*! Synchronizes the backing store, i.e. dirty areas are repainted and flushed. */ @@ -985,6 +1005,17 @@ void QWidgetBackingStore::sync() return; } + if (textureListWatcher && !textureListWatcher->isLocked()) { + textureListWatcher->deleteLater(); + textureListWatcher = 0; + } else if (widgetTextures && widgetTextures->isLocked()) { + if (!textureListWatcher) + textureListWatcher = new QPlatformTextureListWatcher(this); + if (!textureListWatcher->isLocked()) + textureListWatcher->watch(widgetTextures); + return; + } + doSync(); } @@ -1077,7 +1108,7 @@ void QWidgetBackingStore::doSync() delete widgetTextures; widgetTextures = 0; if (tlw->d_func()->textureChildSeen) { - widgetTextures = new QPlatformTextureList; // TODO: implement support for locking + widgetTextures = new QPlatformTextureList; findTextureWidgetsRecursively(tlw, tlw, widgetTextures); } fullUpdatePending = false; diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index c6f6541e1f..2fe58fa4a7 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QPlatformTextureList; +class QWidgetBackingStore; struct BeginPaintInfo { inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {} @@ -69,6 +70,23 @@ struct BeginPaintInfo { uint backingStoreRecreated : 1; }; +class QPlatformTextureListWatcher : public QObject +{ + Q_OBJECT + +public: + QPlatformTextureListWatcher(QWidgetBackingStore *backingStore); + void watch(QPlatformTextureList *textureList); + bool isLocked() const { return m_locked; } + +private slots: + void onLockStatusChanged(bool locked); + +private: + bool m_locked; + QWidgetBackingStore *m_backingStore; +}; + class Q_AUTOTEST_EXPORT QWidgetBackingStore { public: @@ -111,6 +129,8 @@ private: QPoint tlwOffset; + QPlatformTextureListWatcher *textureListWatcher; + void sendUpdateRequest(QWidget *widget, bool updateImmediately); static bool flushPaint(QWidget *widget, const QRegion &rgn); diff --git a/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp b/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp index 09e0dd5419..5752326911 100644 --- a/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp +++ b/tests/manual/qopenglwidget/openglwidget/openglwidget.cpp @@ -58,8 +58,6 @@ #include #include -#include - class OpenGLWidgetPrivate { public: -- cgit v1.2.3