diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-02-21 10:32:07 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-02-26 20:06:11 +0000 |
commit | f9f9bea370fee029b28164c708b29d852e576945 (patch) | |
tree | 1af3042fa450cb6db16fcd94e6d4a450da42914e | |
parent | 5bb4d064945db43d62ea24b5d23bf4b0b4420e38 (diff) |
Compose renderToTexture widgets with sRGB when needed
Just requesting an sRGB texture for a QOpenGLWidget does not lead to
anything useful when it comes to the end result, the content will just get
darkened. For proper operation the target window's default framebuffer
must be sRGB capable and linearization during blending must be enabled.
Task-number: QTBUG-50987
Change-Id: Ibad0657c29a720590fa22c84c4bc303302de6dc0
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | src/gui/painting/qplatformbackingstore.cpp | 34 | ||||
-rw-r--r-- | src/gui/painting/qplatformbackingstore.h | 3 | ||||
-rw-r--r-- | src/widgets/kernel/qopenglwidget.cpp | 30 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 8 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore.cpp | 4 |
6 files changed, 71 insertions, 9 deletions
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index b8bbdefa37..e006fad437 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -70,6 +70,13 @@ #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 #endif +#ifndef GL_FRAMEBUFFER_SRB +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#endif +#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE +#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA +#endif + QT_BEGIN_NAMESPACE class QPlatformBackingStorePrivate @@ -269,7 +276,7 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) } static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, - QOpenGLTextureBlitter *blitter, const QPoint &offset) + QOpenGLTextureBlitter *blitter, const QPoint &offset, bool canUseSrgb) { const QRect clipRect = textures->clipRect(idx); if (clipRect.isEmpty()) @@ -289,7 +296,15 @@ static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, deviceRect(rectInWindow, window).size(), QOpenGLTextureBlitter::OriginBottomLeft); + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + const bool srgb = textures->flags(idx).testFlag(QPlatformTextureList::TextureIsSrgb); + if (srgb && canUseSrgb) + funcs->glEnable(GL_FRAMEBUFFER_SRGB); + blitter->blit(textures->textureId(idx), target, source); + + if (srgb && canUseSrgb) + funcs->glDisable(GL_FRAMEBUFFER_SRGB); } /*! @@ -334,10 +349,23 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window); + bool canUseSrgb = false; + // If there are any sRGB textures in the list, check if the destination + // framebuffer is sRGB capable. + for (int i = 0; i < textures->count(); ++i) { + if (textures->flags(i).testFlag(QPlatformTextureList::TextureIsSrgb)) { + GLint cap = 0; + funcs->glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &cap); + if (cap) + canUseSrgb = true; + break; + } + } + // Textures for renderToTexture widgets. for (int i = 0; i < textures->count(); ++i) { if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) - blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); + blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb); } // Backingstore texture with the normal widgets. @@ -406,7 +434,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set. for (int i = 0; i < textures->count(); ++i) { if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) - blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); + blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb); } funcs->glDisable(GL_BLEND); diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h index ec56aaa002..d1ce67a65d 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -78,7 +78,8 @@ class Q_GUI_EXPORT QPlatformTextureList : public QObject Q_DECLARE_PRIVATE(QPlatformTextureList) public: enum Flag { - StacksOnTop = 0x01 + StacksOnTop = 0x01, + TextureIsSrgb = 0x02 }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index fd45abc8a2..4d45782170 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -581,6 +581,7 @@ public: void recreateFbo(); GLuint textureId() const Q_DECL_OVERRIDE; + QPlatformTextureList::Flags textureListFlags() Q_DECL_OVERRIDE; void initialize(); void invokeUserPaint(); @@ -656,6 +657,35 @@ GLuint QOpenGLWidgetPrivate::textureId() const return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0); } +#ifndef GL_SRGB +#define GL_SRGB 0x8C40 +#endif +#ifndef GL_SRGB8 +#define GL_SRGB8 0x8C41 +#endif +#ifndef GL_SRGB_ALPHA +#define GL_SRGB_ALPHA 0x8C42 +#endif +#ifndef GL_SRGB8_ALPHA8 +#define GL_SRGB8_ALPHA8 0x8C43 +#endif + +QPlatformTextureList::Flags QOpenGLWidgetPrivate::textureListFlags() +{ + QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags(); + switch (textureFormat) { + case GL_SRGB: + case GL_SRGB8: + case GL_SRGB_ALPHA: + case GL_SRGB8_ALPHA8: + flags |= QPlatformTextureList::TextureIsSrgb; + break; + default: + break; + } + return flags; +} + void QOpenGLWidgetPrivate::reset() { Q_Q(QOpenGLWidget); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index dc55c2d5d9..2ced12fb7d 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -67,7 +67,6 @@ # include <private/qmainwindowlayout_p.h> #endif #include <qpa/qplatformwindow.h> -#include <qpa/qplatformbackingstore.h> #include "private/qwidgetwindow_p.h" #include "qpainter.h" #include "qtooltip.h" diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 68e063c25a..858328e618 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -69,6 +69,7 @@ #include "QtWidgets/qgraphicsscene.h" #include "QtWidgets/qgraphicsview.h" #include <private/qgesture_p.h> +#include <qpa/qplatformbackingstore.h> QT_BEGIN_NAMESPACE @@ -81,7 +82,6 @@ class QWidgetBackingStore; class QGraphicsProxyWidget; class QWidgetItemV2; class QOpenGLContext; -class QPlatformTextureList; class QStyle; @@ -630,6 +630,12 @@ public: #ifndef QT_NO_OPENGL virtual GLuint textureId() const { return 0; } + virtual QPlatformTextureList::Flags textureListFlags() { + Q_Q(QWidget); + return q->testAttribute(Qt::WA_AlwaysStackOnTop) + ? QPlatformTextureList::StacksOnTop + : QPlatformTextureList::Flags(0); + } virtual QImage grabFramebuffer() { return QImage(); } virtual void beginBackingStorePainting() { } virtual void endBackingStorePainting() { } diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 781ad9600d..4421218d1d 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -945,9 +945,7 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo { QWidgetPrivate *wd = QWidgetPrivate::get(widget); if (wd->renderToTexture) { - QPlatformTextureList::Flags flags = 0; - if (widget->testAttribute(Qt::WA_AlwaysStackOnTop)) - flags |= QPlatformTextureList::StacksOnTop; + QPlatformTextureList::Flags flags = wd->textureListFlags(); const QRect rect(widget->mapTo(tlw, QPoint()), widget->size()); widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags); } |