From 7fa584254c3ed17b65211c6ae8e05bea66393d93 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 24 Jun 2014 15:05:49 +0200 Subject: Support translucent windows on eglfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-39834 Change-Id: I3f6b041c992365d611aa97a41bc37e80b764b78a Reviewed-by: Jørgen Lind --- .../eglconvenience/qeglcompositor.cpp | 43 +++++++++++++++++++--- .../eglconvenience/qeglplatformbackingstore.cpp | 22 +++++++++-- .../eglconvenience/qeglplatformbackingstore_p.h | 2 +- .../eglconvenience/qeglplatformwindow.cpp | 8 ++++ .../eglconvenience/qeglplatformwindow_p.h | 1 + 5 files changed, 66 insertions(+), 10 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/eglconvenience/qeglcompositor.cpp b/src/platformsupport/eglconvenience/qeglcompositor.cpp index 0e0a2d9375..028f92f3cf 100644 --- a/src/platformsupport/eglconvenience/qeglcompositor.cpp +++ b/src/platformsupport/eglconvenience/qeglcompositor.cpp @@ -105,6 +105,29 @@ void QEGLCompositor::renderAll() windows.at(i)->composited(); } +struct BlendStateBinder +{ + BlendStateBinder() : m_blend(false) { + glDisable(GL_BLEND); + } + void set(bool blend) { + if (blend != m_blend) { + if (blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } else { + glDisable(GL_BLEND); + } + m_blend = blend; + } + } + ~BlendStateBinder() { + if (m_blend) + glDisable(GL_BLEND); + } + bool m_blend; +}; + void QEGLCompositor::render(QEGLPlatformWindow *window) { const QPlatformTextureList *textures = window->textures(); @@ -114,29 +137,37 @@ void QEGLCompositor::render(QEGLPlatformWindow *window) const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size()); glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height()); + float currentOpacity = 1.0f; + BlendStateBinder blend; + 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); + const float opacity = window->window()->opacity(); + if (opacity != currentOpacity) { + currentOpacity = opacity; + m_blitter->setOpacity(currentOpacity); + } if (textures->count() > 1 && i == textures->count() - 1) { // Backingstore for a widget with QOpenGLWidget subwidgets - m_blitter->setSwizzleRB(true); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + blend.set(true); m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); - glDisable(GL_BLEND); } else if (textures->count() == 1) { // A regular QWidget window - m_blitter->setSwizzleRB(true); + const bool translucent = window->window()->requestedFormat().alphaBufferSize() > 0; + blend.set(translucent); m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); } else { // Texture from an FBO belonging to a QOpenGLWidget - m_blitter->setSwizzleRB(false); + blend.set(false); m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft); } } + + m_blitter->setOpacity(1.0f); } QEGLCompositor *QEGLCompositor::instance() diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp index ab92bac37d..8abfbf2763 100644 --- a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp @@ -41,6 +41,7 @@ #include #include +#include #include "qeglplatformbackingstore_p.h" #include "qeglcompositor_p.h" @@ -209,9 +210,16 @@ void QEGLPlatformBackingStore::composited() } } -void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn) +void QEGLPlatformBackingStore::beginPaint(const QRegion ®ion) { - m_dirty |= rgn; + m_dirty |= region; + + if (m_image.hasAlphaChannel()) { + QPainter p(&m_image); + p.setCompositionMode(QPainter::CompositionMode_Source); + foreach (const QRect &r, region.rects()) + p.fillRect(r, Qt::transparent); + } } void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents) @@ -223,7 +231,15 @@ void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticCo if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface)) return; - m_image = QImage(size, QImage::Format_RGB32); + // Child windows do not get real native surfaces and so share the same + // format as the parent, regardless of what has been requested. The + // exception is WA_TranslucentBackground that sets alphaBufferSize in the + // requested format, this has to be taken into account when compositing. + const bool translucent = m_window->window()->requestedFormat().alphaBufferSize() > 0; + const QImage::Format format = translucent ? QImage::Format_RGBA8888 : QImage::Format_RGBX8888; + + m_image = QImage(size, format); + m_window->create(); screen->compositingContext()->makeCurrent(dstWin->window()); diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h index cb1e5999b0..8b0566afa6 100644 --- a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h @@ -61,7 +61,7 @@ public: QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - void beginPaint(const QRegion &) Q_DECL_OVERRIDE; + void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE; void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp index e9b79512ba..a83dd80391 100644 --- a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp @@ -127,4 +127,12 @@ WId QEGLPlatformWindow::winId() const return m_winId; } +void QEGLPlatformWindow::setOpacity(qreal) +{ + if (!isRaster()) + qWarning("eglfs: Cannot set opacity for non-raster windows"); + + // Nothing to do here. The opacity is stored in the QWindow. +} + QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h index 17a1d07a79..8c77d31fef 100644 --- a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h @@ -64,6 +64,7 @@ public: bool isRaster() const; WId winId() const Q_DECL_OVERRIDE; + void setOpacity(qreal opacity) Q_DECL_OVERRIDE; virtual EGLNativeWindowType eglWindow() const = 0; -- cgit v1.2.3