diff options
Diffstat (limited to 'src/platformsupport')
12 files changed, 243 insertions, 212 deletions
diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index 8ada53d2c1..d102203d5e 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -16,16 +16,12 @@ contains(QT_CONFIG,egl) { $$PWD/qeglplatformcursor_p.h \ $$PWD/qeglplatformwindow_p.h \ $$PWD/qeglplatformscreen_p.h \ - $$PWD/qeglcompositor_p.h \ - $$PWD/qeglplatformbackingstore_p.h \ $$PWD/qeglplatformintegration_p.h SOURCES += \ $$PWD/qeglplatformcursor.cpp \ $$PWD/qeglplatformwindow.cpp \ $$PWD/qeglplatformscreen.cpp \ - $$PWD/qeglcompositor.cpp \ - $$PWD/qeglplatformbackingstore.cpp \ $$PWD/qeglplatformintegration.cpp } } diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp index fea2ae2369..09011e6e58 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp @@ -43,6 +43,7 @@ #include <QtPlatformSupport/private/qgenericunixservices_p.h> #include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> #include <QtPlatformSupport/private/qfbvthandler_p.h> +#include <QtPlatformSupport/private/qopenglcompositorbackingstore_p.h> #if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) #include <QtPlatformSupport/private/qevdevmousemanager_p.h> @@ -59,7 +60,6 @@ #include "qeglplatformintegration_p.h" #include "qeglplatformcontext_p.h" #include "qeglplatformwindow_p.h" -#include "qeglplatformbackingstore_p.h" #include "qeglplatformscreen_p.h" #include "qeglplatformcursor_p.h" @@ -141,7 +141,9 @@ QPlatformFontDatabase *QEGLPlatformIntegration::fontDatabase() const QPlatformBackingStore *QEGLPlatformIntegration::createPlatformBackingStore(QWindow *window) const { - return new QEGLPlatformBackingStore(window); + QOpenGLCompositorBackingStore *bs = new QOpenGLCompositorBackingStore(window); + static_cast<QEGLPlatformWindow *>(window->handle())->setBackingStore(bs); + return bs; } QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window) const @@ -156,10 +158,9 @@ QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window) QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { - QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(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; + QOpenGLContext *compositingContext = QOpenGLCompositor::instance()->context(); QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle(); QVariant nativeHandle = context->nativeHandle(); QPlatformOpenGLContext *platformContext = createContext(context->format(), diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp index fd577a48d7..fd9befb575 100644 --- a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp @@ -31,8 +31,8 @@ ** ****************************************************************************/ -#include "qeglcompositor_p.h" #include "qeglplatformscreen_p.h" +#include <QtPlatformSupport/private/qopenglcompositor_p.h> QT_BEGIN_NAMESPACE @@ -42,19 +42,6 @@ QT_BEGIN_NAMESPACE \since 5.2 \internal \ingroup qpa - - This class provides a lightweight base for QPlatformScreen - implementations. It covers basic window stack management which is - necessary when compositing multiple raster (widget-based) windows - together into one single native surface. - - Reimplementing the virtuals are essential when using - QEGLPlatformBackingStore. The context and the window returned from - these are the ones that are used when compositing the textures - generated from the raster (widget) based windows. - - \note It is up to the QEGLPlatformWindow subclasses to use the - functions, like addWindow(), removeWindow(), etc., provided here. */ QEGLPlatformScreen::QEGLPlatformScreen(EGLDisplay dpy) @@ -64,39 +51,7 @@ QEGLPlatformScreen::QEGLPlatformScreen(EGLDisplay dpy) QEGLPlatformScreen::~QEGLPlatformScreen() { - QEGLCompositor::destroy(); -} - -void QEGLPlatformScreen::addWindow(QEGLPlatformWindow *window) -{ - if (!m_windows.contains(window)) { - m_windows.append(window); - topWindowChanged(window); - } -} - -void QEGLPlatformScreen::removeWindow(QEGLPlatformWindow *window) -{ - m_windows.removeOne(window); - if (!m_windows.isEmpty()) - topWindowChanged(m_windows.last()); -} - -void QEGLPlatformScreen::moveToTop(QEGLPlatformWindow *window) -{ - m_windows.removeOne(window); - m_windows.append(window); - topWindowChanged(window); -} - -void QEGLPlatformScreen::changeWindowIndex(QEGLPlatformWindow *window, int newIdx) -{ - int idx = m_windows.indexOf(window); - if (idx != -1 && idx != newIdx) { - m_windows.move(idx, newIdx); - if (newIdx == m_windows.size() - 1) - topWindowChanged(m_windows.last()); - } + QOpenGLCompositor::destroy(); } QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h index bb1d26d7d2..e9d3363a66 100644 --- a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h @@ -60,22 +60,9 @@ public: QEGLPlatformScreen(EGLDisplay dpy); ~QEGLPlatformScreen(); - QList<QEGLPlatformWindow *> windows() const { return m_windows; } - - void addWindow(QEGLPlatformWindow *window); - void removeWindow(QEGLPlatformWindow *window); - void moveToTop(QEGLPlatformWindow *window); - void changeWindowIndex(QEGLPlatformWindow *window, int newIdx); - - virtual void topWindowChanged(QEGLPlatformWindow *window) { Q_UNUSED(window); } - EGLDisplay display() const { return m_dpy; } - virtual QEGLPlatformWindow *compositingWindow() = 0; - virtual QOpenGLContext *compositingContext() = 0; - private: - QList<QEGLPlatformWindow *> m_windows; EGLDisplay m_dpy; }; diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp index af4c907e85..5e5c879a22 100644 --- a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp @@ -32,9 +32,10 @@ ****************************************************************************/ #include <qpa/qwindowsysteminterface.h> +#include <QtPlatformSupport/private/qopenglcompositor_p.h> +#include <QtPlatformSupport/private/qopenglcompositorbackingstore_p.h> #include "qeglplatformwindow_p.h" -#include "qeglplatformbackingstore_p.h" #include "qeglplatformscreen_p.h" QT_BEGIN_NAMESPACE @@ -47,7 +48,7 @@ QT_BEGIN_NAMESPACE \ingroup qpa Lightweight class providing some basic platform window operations - and interfacing with QEGLPlatformBackingStore. + and interfacing with QOpenGLCompositorBackingStore. Almost no QPlatformWindow functions are implemented here. This is intentional because different platform plugins may use different @@ -57,13 +58,15 @@ QT_BEGIN_NAMESPACE enforce anything for these functions. \note Subclasses are responsible for invoking this class' - implementation of create(). When using QEGLPlatformScreen, the - subclasses of this class are expected to utilize the window stack - management functions (addWindow() etc.) provided there. + implementation of create() and are expected to utilize the window + stack management functions (addWindow() etc.) in + QOpenGLCompositor. */ QEGLPlatformWindow::QEGLPlatformWindow(QWindow *w) : QPlatformWindow(w), + m_backingStore(0), + m_raster(false), m_winId(0) { } @@ -100,6 +103,11 @@ bool QEGLPlatformWindow::isRaster() const return m_raster || window()->surfaceType() == QSurface::RasterGLSurface; } +QWindow *QEGLPlatformWindow::sourceWindow() const +{ + return window(); +} + const QPlatformTextureList *QEGLPlatformWindow::textures() const { if (m_backingStore) @@ -108,10 +116,10 @@ const QPlatformTextureList *QEGLPlatformWindow::textures() const return 0; } -void QEGLPlatformWindow::composited() +void QEGLPlatformWindow::endCompositing() { if (m_backingStore) - m_backingStore->composited(); + m_backingStore->notifyComposited(); } WId QEGLPlatformWindow::winId() const diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h index 3a19301e5d..947f02aeb5 100644 --- a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h @@ -46,33 +46,36 @@ // #include <qpa/qplatformwindow.h> +#include <QtPlatformSupport/private/qopenglcompositor_p.h> #include <EGL/egl.h> QT_BEGIN_NAMESPACE -class QEGLPlatformBackingStore; +class QOpenGLCompositorBackingStore; class QPlatformTextureList; -class QEGLPlatformWindow : public QPlatformWindow +class QEGLPlatformWindow : public QPlatformWindow, public QOpenGLCompositorWindow { public: QEGLPlatformWindow(QWindow *w); virtual void create(); - QEGLPlatformBackingStore *backingStore() { return m_backingStore; } - void setBackingStore(QEGLPlatformBackingStore *backingStore) { m_backingStore = backingStore; } - const QPlatformTextureList *textures() const; - void composited(); + QOpenGLCompositorBackingStore *backingStore() { return m_backingStore; } + void setBackingStore(QOpenGLCompositorBackingStore *backingStore) { m_backingStore = backingStore; } bool isRaster() const; + QWindow *sourceWindow() const Q_DECL_OVERRIDE; + const QPlatformTextureList *textures() const Q_DECL_OVERRIDE; + void endCompositing() Q_DECL_OVERRIDE; + WId winId() const Q_DECL_OVERRIDE; void setOpacity(qreal opacity) Q_DECL_OVERRIDE; virtual EGLNativeWindowType eglWindow() const = 0; private: - QEGLPlatformBackingStore *m_backingStore; + QOpenGLCompositorBackingStore *m_backingStore; bool m_raster; WId m_winId; }; diff --git a/src/platformsupport/platformcompositor/platformcompositor.pri b/src/platformsupport/platformcompositor/platformcompositor.pri new file mode 100644 index 0000000000..923d7225da --- /dev/null +++ b/src/platformsupport/platformcompositor/platformcompositor.pri @@ -0,0 +1,7 @@ +contains(QT_CONFIG, opengl) { + SOURCES += $$PWD/qopenglcompositor.cpp \ + $$PWD/qopenglcompositorbackingstore.cpp + + HEADERS += $$PWD/qopenglcompositor_p.h \ + $$PWD/qopenglcompositorbackingstore_p.h +} diff --git a/src/platformsupport/eglconvenience/qeglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp index 5866edc48d..3fefdc4935 100644 --- a/src/platformsupport/eglconvenience/qeglcompositor.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp @@ -32,23 +32,46 @@ ****************************************************************************/ #include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLShaderProgram> -#include <QtGui/QOpenGLFramebufferObject> -#include <QtGui/private/qopengltextureblitter_p.h> +#include <QtGui/QWindow> +#include <QtGui/QMatrix4x4> #include <qpa/qplatformbackingstore.h> -#include "qeglcompositor_p.h" -#include "qeglplatformwindow_p.h" -#include "qeglplatformscreen_p.h" +#include "qopenglcompositor_p.h" QT_BEGIN_NAMESPACE -static QEGLCompositor *compositor = 0; +/*! + \class QOpenGLCompositor + \brief A generic OpenGL-based compositor + \since 5.4 + \internal + \ingroup qpa -QEGLCompositor::QEGLCompositor() + This class provides a lightweight compositor that maintains the + basic stacking order of windows and composites them by drawing + textured quads via OpenGL. + + It it meant to be used by platform plugins that run without a + windowing system. + + It is up to the platform plugin to manage the lifetime of the + compositor (instance(), destroy()), set the correct destination + context and window as early as possible (setTargetWindow()), + register the composited windows as they are shown, activated, + raised and lowered (addWindow(), moveToTop(), etc.), and to + schedule repaints (update()). + + \note To get support for QWidget-based windows, just use + QOpenGLCompositorBackingStore. It will automatically create + textures from the raster-rendered content and trigger the + necessary repaints. + */ + +static QOpenGLCompositor *compositor = 0; + +QOpenGLCompositor::QOpenGLCompositor() : m_context(0), - m_window(0), - m_blitter(0) + m_targetWindow(0) { Q_ASSERT(!compositor); m_updateTimer.setSingleShot(true); @@ -56,45 +79,51 @@ QEGLCompositor::QEGLCompositor() connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll())); } -QEGLCompositor::~QEGLCompositor() +QOpenGLCompositor::~QOpenGLCompositor() { Q_ASSERT(compositor == this); - if (m_blitter) { - m_blitter->destroy(); - delete m_blitter; - } + m_blitter.destroy(); compositor = 0; } -void QEGLCompositor::schedule(QOpenGLContext *context, QEGLPlatformWindow *window) +void QOpenGLCompositor::setTarget(QOpenGLContext *context, QWindow *targetWindow) { m_context = context; - m_window = window; + m_targetWindow = targetWindow; +} + +void QOpenGLCompositor::update() +{ if (!m_updateTimer.isActive()) m_updateTimer.start(); } -void QEGLCompositor::renderAll() +void QOpenGLCompositor::renderAll() { - Q_ASSERT(m_context && m_window); - m_context->makeCurrent(m_window->window()); + Q_ASSERT(m_context && m_targetWindow); + m_context->makeCurrent(m_targetWindow); - if (!m_blitter) { - m_blitter = new QOpenGLTextureBlitter; - m_blitter->create(); - } - m_blitter->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size()); + glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height()); - QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); - QList<QEGLPlatformWindow *> windows = screen->windows(); - for (int i = 0; i < windows.size(); ++i) - render(windows.at(i)); + if (!m_blitter.isCreated()) + m_blitter.create(); - m_blitter->release(); - m_context->swapBuffers(m_window->window()); + m_blitter.bind(); - for (int i = 0; i < windows.size(); ++i) - windows.at(i)->composited(); + for (int i = 0; i < m_windows.size(); ++i) + m_windows.at(i)->beginCompositing(); + + for (int i = 0; i < m_windows.size(); ++i) + render(m_windows.at(i)); + + m_blitter.release(); + m_context->swapBuffers(m_targetWindow); + + for (int i = 0; i < m_windows.size(); ++i) + m_windows.at(i)->endCompositing(); } struct BlendStateBinder @@ -120,41 +149,38 @@ struct BlendStateBinder bool m_blend; }; -void QEGLCompositor::render(QEGLPlatformWindow *window) +void QOpenGLCompositor::render(QOpenGLCompositorWindow *window) { 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()); - + const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size()); float currentOpacity = 1.0f; BlendStateBinder blend; for (int i = 0; i < textures->count(); ++i) { uint textureId = textures->textureId(i); - QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), - targetWindowRect); - const float opacity = window->window()->opacity(); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); + const float opacity = window->sourceWindow()->opacity(); if (opacity != currentOpacity) { currentOpacity = opacity; - m_blitter->setOpacity(currentOpacity); + m_blitter.setOpacity(currentOpacity); } if (textures->count() > 1 && i == textures->count() - 1) { // Backingstore for a widget with QOpenGLWidget subwidgets blend.set(true); - m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); + m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); } else if (textures->count() == 1) { // A regular QWidget window - const bool translucent = window->window()->requestedFormat().alphaBufferSize() > 0; + const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0; blend.set(translucent); - m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); + m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); } else if (!textures->stacksOnTop(i)) { // Texture from an FBO belonging to a QOpenGLWidget blend.set(false); - m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft); + m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft); } } @@ -162,24 +188,56 @@ void QEGLCompositor::render(QEGLPlatformWindow *window) if (textures->stacksOnTop(i)) { QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); blend.set(true); - m_blitter->blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft); + m_blitter.blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft); } } - m_blitter->setOpacity(1.0f); + m_blitter.setOpacity(1.0f); } -QEGLCompositor *QEGLCompositor::instance() +QOpenGLCompositor *QOpenGLCompositor::instance() { if (!compositor) - compositor = new QEGLCompositor; + compositor = new QOpenGLCompositor; return compositor; } -void QEGLCompositor::destroy() +void QOpenGLCompositor::destroy() { delete compositor; compositor = 0; } +void QOpenGLCompositor::addWindow(QOpenGLCompositorWindow *window) +{ + if (!m_windows.contains(window)) { + m_windows.append(window); + emit topWindowChanged(window); + } +} + +void QOpenGLCompositor::removeWindow(QOpenGLCompositorWindow *window) +{ + m_windows.removeOne(window); + if (!m_windows.isEmpty()) + emit topWindowChanged(m_windows.last()); +} + +void QOpenGLCompositor::moveToTop(QOpenGLCompositorWindow *window) +{ + m_windows.removeOne(window); + m_windows.append(window); + emit topWindowChanged(window); +} + +void QOpenGLCompositor::changeWindowIndex(QOpenGLCompositorWindow *window, int newIdx) +{ + int idx = m_windows.indexOf(window); + if (idx != -1 && idx != newIdx) { + m_windows.move(idx, newIdx); + if (newIdx == m_windows.size() - 1) + emit topWindowChanged(m_windows.last()); + } +} + QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglcompositor_p.h b/src/platformsupport/platformcompositor/qopenglcompositor_p.h index 1401fbdd55..9c876f5af1 100644 --- a/src/platformsupport/eglconvenience/qeglcompositor_p.h +++ b/src/platformsupport/platformcompositor/qopenglcompositor_p.h @@ -31,8 +31,8 @@ ** ****************************************************************************/ -#ifndef QEGLCOMPOSITOR_H -#define QEGLCOMPOSITOR_H +#ifndef QOPENGLCOMPOSITOR_H +#define QOPENGLCOMPOSITOR_H // // W A R N I N G @@ -46,38 +46,62 @@ // #include <QtCore/QTimer> +#include <QtGui/private/qopengltextureblitter_p.h> QT_BEGIN_NAMESPACE class QOpenGLContext; -class QOpenGLTextureBlitter; -class QEGLPlatformWindow; +class QWindow; +class QPlatformTextureList; -class QEGLCompositor : public QObject +class QOpenGLCompositorWindow +{ +public: + virtual QWindow *sourceWindow() const = 0; + virtual const QPlatformTextureList *textures() const = 0; + virtual void beginCompositing() { } + virtual void endCompositing() { } +}; + +class QOpenGLCompositor : public QObject { Q_OBJECT public: - void schedule(QOpenGLContext *context, QEGLPlatformWindow *window); - - static QEGLCompositor *instance(); + static QOpenGLCompositor *instance(); static void destroy(); + void setTarget(QOpenGLContext *context, QWindow *window); + QOpenGLContext *context() const { return m_context; } + QWindow *targetWindow() const { return m_targetWindow; } + + void update(); + + QList<QOpenGLCompositorWindow *> windows() const { return m_windows; } + void addWindow(QOpenGLCompositorWindow *window); + void removeWindow(QOpenGLCompositorWindow *window); + void moveToTop(QOpenGLCompositorWindow *window); + void changeWindowIndex(QOpenGLCompositorWindow *window, int newIdx); + +signals: + void topWindowChanged(QOpenGLCompositorWindow *window); + private slots: void renderAll(); private: - QEGLCompositor(); - ~QEGLCompositor(); + QOpenGLCompositor(); + ~QOpenGLCompositor(); - void render(QEGLPlatformWindow *window); + void render(QOpenGLCompositorWindow *window); QOpenGLContext *m_context; - QEGLPlatformWindow *m_window; + QWindow *m_targetWindow; QTimer m_updateTimer; - QOpenGLTextureBlitter *m_blitter; + QOpenGLTextureBlitter m_blitter; + QList<QOpenGLCompositorWindow *> m_windows; }; QT_END_NAMESPACE -#endif // QEGLCOMPOSITOR_H +#endif // QOPENGLCOMPOSITOR_H diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp index 43c18573f2..9c254bead3 100644 --- a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp @@ -31,62 +31,58 @@ ** ****************************************************************************/ -#include <QtGui/QOpenGLShaderProgram> #include <QtGui/QOpenGLContext> +#include <QtGui/QWindow> #include <QtGui/QPainter> +#include <qpa/qplatformbackingstore.h> -#include "qeglplatformbackingstore_p.h" -#include "qeglcompositor_p.h" -#include "qeglplatformwindow_p.h" -#include "qeglplatformscreen_p.h" +#include "qopenglcompositorbackingstore_p.h" +#include "qopenglcompositor_p.h" QT_BEGIN_NAMESPACE /*! - \class QEGLPlatformBackingStore - \brief A backing store implementation for EGL and GLES. - \since 5.2 + \class QOpenGLCompositorBackingStore + \brief A backing store implementation for OpenGL + \since 5.4 \internal \ingroup qpa This implementation uploads raster-rendered widget windows into - textures and composites them onto a single native window using - QEGLCompositor. This means that multiple top-level widgets are - supported without creating actual native windows for each of them. - - The class is ready to be used as-is, the default - QEGLPlatformIntegration::createPlatformBackingStore() - implementation creates an instance which is ready to be used - without further customization. - - If QEGLCompositor is not suitable, this backing store - implementation can also be used without it. In this case a - subclass must reimplement composite() and schedule an update in - its custom compositor when this function is called. The textures - are accessible via QEGLPlatformWindow::texture(). + textures. It is meant to be used with QOpenGLCompositor that + composites the textures onto a single native window using OpenGL. + This means that multiple top-level widgets are supported without + creating actual native windows for each of them. + + \note It is important to call notifyComposited() from the + corresponding platform window's endCompositing() callback + (inherited from QOpenGLCompositorWindow). + + \note When implementing QOpenGLCompositorWindow::textures() for + windows of type RasterSurface or RasterGLSurface, simply return + the list provided by this class' textures(). */ -QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window) +QOpenGLCompositorBackingStore::QOpenGLCompositorBackingStore(QWindow *window) : QPlatformBackingStore(window), - m_window(static_cast<QEGLPlatformWindow *>(window->handle())), + m_window(window), m_bsTexture(0), m_textures(new QPlatformTextureList), m_lockedWidgetTextures(0) { - m_window->setBackingStore(this); } -QEGLPlatformBackingStore::~QEGLPlatformBackingStore() +QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore() { delete m_textures; } -QPaintDevice *QEGLPlatformBackingStore::paintDevice() +QPaintDevice *QOpenGLCompositorBackingStore::paintDevice() { return &m_image; } -void QEGLPlatformBackingStore::updateTexture() +void QOpenGLCompositorBackingStore::updateTexture() { if (!m_bsTexture) { glGenTextures(1, &m_bsTexture); @@ -134,7 +130,7 @@ void QEGLPlatformBackingStore::updateTexture() } } -void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) +void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { // Called for ordinary raster windows. This is rare since RasterGLSurface // support is claimed which leads to having all QWidget windows marked as @@ -144,35 +140,38 @@ void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, con Q_UNUSED(region); Q_UNUSED(offset); - QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); - QEGLPlatformWindow *dstWin = screen->compositingWindow(); - if (!dstWin || !dstWin->isRaster()) + QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); + QOpenGLContext *dstCtx = compositor->context(); + QWindow *dstWin = compositor->targetWindow(); + if (!dstWin) return; - screen->compositingContext()->makeCurrent(dstWin->window()); + dstCtx->makeCurrent(dstWin); updateTexture(); m_textures->clear(); m_textures->appendTexture(m_bsTexture, window->geometry()); - composite(screen->compositingContext(), dstWin); + + compositor->update(); } -void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, +void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, QOpenGLContext *context, bool translucentBackground) { - // QOpenGLWidget content provided as textures. The raster content should go on top. + // QOpenGLWidget/QQuickWidget content provided as textures. The raster content should go on top. Q_UNUSED(region); Q_UNUSED(offset); Q_UNUSED(context); Q_UNUSED(translucentBackground); - QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); - QEGLPlatformWindow *dstWin = screen->compositingWindow(); - if (!dstWin || !dstWin->isRaster()) + QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); + QOpenGLContext *dstCtx = compositor->context(); + QWindow *dstWin = compositor->targetWindow(); + if (!dstWin) return; - screen->compositingContext()->makeCurrent(dstWin->window()); + dstCtx->makeCurrent(dstWin); m_textures->clear(); for (int i = 0; i < textures->count(); ++i) @@ -184,15 +183,10 @@ void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &r textures->lock(true); m_lockedWidgetTextures = textures; - composite(screen->compositingContext(), dstWin); -} - -void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWindow *window) -{ - QEGLCompositor::instance()->schedule(context, window); + compositor->update(); } -void QEGLPlatformBackingStore::composited() +void QOpenGLCompositorBackingStore::notifyComposited() { if (m_lockedWidgetTextures) { QPlatformTextureList *textureList = m_lockedWidgetTextures; @@ -201,7 +195,7 @@ void QEGLPlatformBackingStore::composited() } } -void QEGLPlatformBackingStore::beginPaint(const QRegion ®ion) +void QOpenGLCompositorBackingStore::beginPaint(const QRegion ®ion) { m_dirty |= region; @@ -213,27 +207,28 @@ void QEGLPlatformBackingStore::beginPaint(const QRegion ®ion) } } -void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents) +void QOpenGLCompositorBackingStore::resize(const QSize &size, const QRegion &staticContents) { Q_UNUSED(staticContents); - QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); - QEGLPlatformWindow *dstWin = screen->compositingWindow(); - if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface)) + QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); + QOpenGLContext *dstCtx = compositor->context(); + QWindow *dstWin = compositor->targetWindow(); + if (!dstWin) return; m_image = QImage(size, QImage::Format_RGBA8888); m_window->create(); - screen->compositingContext()->makeCurrent(dstWin->window()); + dstCtx->makeCurrent(dstWin); if (m_bsTexture) { glDeleteTextures(1, &m_bsTexture); m_bsTexture = 0; } } -QImage QEGLPlatformBackingStore::toImage() const +QImage QOpenGLCompositorBackingStore::toImage() const { return m_image; } diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore_p.h index 502ca5a639..0501cd868c 100644 --- a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h +++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore_p.h @@ -31,8 +31,8 @@ ** ****************************************************************************/ -#ifndef QEGLPLATFORMBACKINGSTORE_H -#define QEGLPLATFORMBACKINGSTORE_H +#ifndef QOPENGLCOMPOSITORBACKINGSTORE_H +#define QOPENGLCOMPOSITORBACKINGSTORE_H // // W A R N I N G @@ -46,7 +46,6 @@ // #include <qpa/qplatformbackingstore.h> - #include <QImage> #include <QRegion> @@ -54,13 +53,12 @@ QT_BEGIN_NAMESPACE class QOpenGLContext; class QPlatformTextureList; -class QEGLPlatformWindow; -class QEGLPlatformBackingStore : public QPlatformBackingStore +class QOpenGLCompositorBackingStore : public QPlatformBackingStore { public: - QEGLPlatformBackingStore(QWindow *window); - ~QEGLPlatformBackingStore(); + QOpenGLCompositorBackingStore(QWindow *window); + ~QOpenGLCompositorBackingStore(); QPaintDevice *paintDevice() Q_DECL_OVERRIDE; @@ -76,14 +74,12 @@ public: const QPlatformTextureList *textures() const { return m_textures; } - virtual void composite(QOpenGLContext *context, QEGLPlatformWindow *window); - - void composited(); + void notifyComposited(); private: void updateTexture(); - QEGLPlatformWindow *m_window; + QWindow *m_window; QImage m_image; QRegion m_dirty; uint m_bsTexture; @@ -93,4 +89,4 @@ private: QT_END_NAMESPACE -#endif // QEGLPLATFORMBACKINGSTORE_H +#endif // QOPENGLCOMPOSITORBACKINGSTORE_H diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 32ce2e3887..39cbd9d181 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -21,5 +21,6 @@ include(themes/themes.pri) include(accessibility/accessibility.pri) include(linuxaccessibility/linuxaccessibility.pri) include(clipboard/clipboard.pri) +include(platformcompositor/platformcompositor.pri) load(qt_module) |