From 5d49d5a224f8bee7edabd73bcac43f7bdb9f0bed Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 22 Aug 2014 12:41:42 +0200 Subject: [PATCH] Support RasterGLSurface windows In an attempt to make QOpenGLWidget and QQuickWidget working on Wayland. Since Qt 5.3 all widget windows are of type RasterGLSurface (given that the plugin reports this capability which wayland will, with this patch). Such a window can behave either like a raster or an OpenGL window. This concept maps badly to platform plugins that have a rigid separation between raster and OpenGL platform window implementations. From now on, the OpenGL window implementation, that is used pretty much always, except for raw RasterSurface windows, must be prepared to behave like a raster window too, which involves having a backingstore. Change-Id: I0226704b8d5893843fcae68059c5fe9ad2f5e761 Reviewed-by: Robin Burchell --- .../qwaylandclientbufferintegration_p.h | 2 + .../platforms/wayland/qwaylandintegration.cpp | 10 ++-- .../wayland/qwaylandshmbackingstore.cpp | 47 ++++++++++++------- .../wayland/qwaylandshmbackingstore_p.h | 7 ++- .../platforms/wayland/qwaylandshmwindow.cpp | 7 --- .../platforms/wayland/qwaylandshmwindow_p.h | 13 ----- .../platforms/wayland/qwaylandwindow_p.h | 6 +++ 7 files changed, 50 insertions(+), 42 deletions(-) diff --git a/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h b/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h index 7d79f326330..be594984b56 100644 --- a/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h +++ b/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h @@ -62,6 +62,8 @@ public: virtual void initialize(QWaylandDisplay *display) = 0; + virtual bool isValid() const { return true; } + virtual bool supportsThreadedOpenGL() const { return false; } virtual QWaylandWindow *createEglWindow(QWindow *window) = 0; diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 0c90626964c..3b6d4acf944 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -42,9 +42,9 @@ #include "qwaylandintegration_p.h" #include "qwaylanddisplay_p.h" +#include "qwaylandshmwindow_p.h" #include "qwaylandinputcontext_p.h" #include "qwaylandshmbackingstore_p.h" -#include "qwaylandshmwindow_p.h" #include "qwaylandnativeinterface_p.h" #include "qwaylandclipboard_p.h" #include "qwaylanddnd_p.h" @@ -162,14 +162,18 @@ bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) co case MultipleWindows: case NonFullScreenWindows: return true; + case RasterGLSurface: + return true; default: return QPlatformIntegration::hasCapability(cap); } } QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const { - if (window->surfaceType() == QWindow::OpenGLSurface && mDisplay->clientBufferIntegration()) + if ((window->surfaceType() == QWindow::OpenGLSurface || window->surfaceType() == QWindow::RasterGLSurface) + && mDisplay->clientBufferIntegration()) return mDisplay->clientBufferIntegration()->createEglWindow(window); + return new QWaylandShmWindow(window); } @@ -255,7 +259,7 @@ QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() if (!mClientBufferIntegrationInitialized) const_cast(this)->initializeClientBufferIntegration(); - return mClientBufferIntegration; + return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration : 0; } QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() const diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index 0677ed0d398..14e1285d37b 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp @@ -39,14 +39,12 @@ ** ****************************************************************************/ #include "qwaylandshmbackingstore_p.h" - -#include - +#include "qwaylandwindow_p.h" #include "qwaylanddisplay_p.h" -#include "qwaylandshmwindow_p.h" #include "qwaylandscreen_p.h" #include "qwaylanddecoration_p.h" +#include #include #include @@ -156,9 +154,7 @@ QWaylandShmBackingStore::~QWaylandShmBackingStore() QPaintDevice *QWaylandShmBackingStore::paintDevice() { - if (!windowDecoration()) - return mBackBuffer->image(); - return mBackBuffer->imageInsideMargins(windowDecorationMargins()); + return contentSurface(); } void QWaylandShmBackingStore::beginPaint(const QRegion &) @@ -166,13 +162,11 @@ void QWaylandShmBackingStore::beginPaint(const QRegion &) mPainting = true; ensureSize(); - if (waylandWindow()->attached() && mBackBuffer == waylandWindow()->attached() && mFrameCallback) { - QWaylandShmWindow *waylandWindow = static_cast(window()->handle()); - Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm); - waylandWindow->waitForFrameSync(); - } + QWaylandWindow *window = waylandWindow(); + if (window->attached() && mBackBuffer == window->attached() && mFrameCallback) + window->waitForFrameSync(); - waylandWindow()->setCanResize(false); + window->setCanResize(false); } void QWaylandShmBackingStore::endPaint() @@ -190,9 +184,15 @@ void QWaylandShmBackingStore::ensureSize() void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { + // Invoked when the window is of type RasterSurface or when the window is + // RasterGLSurface and there are no child widgets requiring OpenGL composition. + + // For the case of RasterGLSurface + having to compose, the composeAndFlush() is + // called instead. The default implementation from QPlatformBackingStore is sufficient + // however so no need to reimplement that. + Q_UNUSED(window); Q_UNUSED(offset); - Q_ASSERT(waylandWindow()->windowType() == QWaylandWindow::Shm); if (windowDecoration() && windowDecoration()->isDirty()) updateDecorations(); @@ -260,6 +260,11 @@ QImage *QWaylandShmBackingStore::entireSurface() const return mBackBuffer->image(); } +QImage *QWaylandShmBackingStore::contentSurface() const +{ + return windowDecoration() ? mBackBuffer->imageInsideMargins(windowDecorationMargins()) : mBackBuffer->image(); +} + void QWaylandShmBackingStore::updateDecorations() { QPainter decorationPainter(entireSurface()); @@ -302,11 +307,19 @@ QMargins QWaylandShmBackingStore::windowDecorationMargins() const return QMargins(); } -QWaylandShmWindow *QWaylandShmBackingStore::waylandWindow() const +QWaylandWindow *QWaylandShmBackingStore::waylandWindow() const { - return static_cast(window()->handle()); + return static_cast(window()->handle()); } +QImage QWaylandShmBackingStore::toImage() const +{ + // Invoked from QPlatformBackingStore::composeAndFlush() that is called + // instead of flush() for widgets that have renderToTexture children + // (QOpenGLWidget, QQuickWidget). + + return *contentSurface(); +} void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time) { @@ -315,7 +328,7 @@ void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t t static_cast(data); if (callback != self->mFrameCallback) // others, like QWaylandWindow, may trigger callbacks too return; - QWaylandShmWindow *window = self->waylandWindow(); + QWaylandWindow *window = self->waylandWindow(); wl_callback_destroy(self->mFrameCallback); self->mFrameCallback = 0; diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h index 6097b5282c8..33f363f6873 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QWaylandDisplay; class QWaylandDecoration; -class QWaylandShmWindow; +class QWaylandWindow; class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer { public: @@ -87,11 +87,14 @@ public: QMargins windowDecorationMargins() const; QImage *entireSurface() const; + QImage *contentSurface() const; void ensureSize(); - QWaylandShmWindow *waylandWindow() const; + QWaylandWindow *waylandWindow() const; void iterateBuffer(); + QImage toImage() const Q_DECL_OVERRIDE; + private: void updateDecorations(); diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp index de87682ce70..431ed2fdb97 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp @@ -51,13 +51,11 @@ QT_BEGIN_NAMESPACE QWaylandShmWindow::QWaylandShmWindow(QWindow *window) : QWaylandWindow(window) - , mBackingStore(0) { } QWaylandShmWindow::~QWaylandShmWindow() { - } QWaylandWindow::WindowType QWaylandShmWindow::windowType() const @@ -65,9 +63,4 @@ QWaylandWindow::WindowType QWaylandShmWindow::windowType() const return QWaylandWindow::Shm; } -void QWaylandShmWindow::setBackingStore(QWaylandShmBackingStore *backingStore) -{ - mBackingStore = backingStore; -} - QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow_p.h b/src/plugins/platforms/wayland/qwaylandshmwindow_p.h index 83479f31303..47ee742699d 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmwindow_p.h @@ -47,8 +47,6 @@ QT_BEGIN_NAMESPACE -class QWaylandShmBackingStore; - class Q_WAYLAND_CLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow { public: @@ -57,19 +55,8 @@ public: WindowType windowType() const; QSurfaceFormat format() const { return QSurfaceFormat(); } - - void setBackingStore(QWaylandShmBackingStore *backingStore); - QWaylandShmBackingStore *backingStore() const; - -private: - QWaylandShmBackingStore *mBackingStore; }; -inline QWaylandShmBackingStore *QWaylandShmWindow::backingStore() const -{ - return mBackingStore; -} - QT_END_NAMESPACE #endif // QWAYLANDSHMWINDOW_H diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 9c0be84c6a5..0d0833e54eb 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -63,6 +63,7 @@ class QWaylandSubSurface; class QWaylandDecoration; class QWaylandInputDevice; class QWaylandScreen; +class QWaylandShmBackingStore; class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowConfigure { @@ -179,6 +180,9 @@ public: QVariant property(const QString &name); QVariant property(const QString &name, const QVariant &defaultValue); + void setBackingStore(QWaylandShmBackingStore *backingStore) { mBackingStore = backingStore; } + QWaylandShmBackingStore *backingStore() const { return mBackingStore; } + public slots: void requestResize(); @@ -216,6 +220,8 @@ protected: Qt::WindowState mState; + QWaylandShmBackingStore *mBackingStore; + private: bool setWindowStateInternal(Qt::WindowState flags); void setGeometry_helper(const QRect &rect);