summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2017-02-21 10:32:07 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2017-02-26 20:06:11 +0000
commitf9f9bea370fee029b28164c708b29d852e576945 (patch)
tree1af3042fa450cb6db16fcd94e6d4a450da42914e
parent5bb4d064945db43d62ea24b5d23bf4b0b4420e38 (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.cpp34
-rw-r--r--src/gui/painting/qplatformbackingstore.h3
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp30
-rw-r--r--src/widgets/kernel/qwidget.cpp1
-rw-r--r--src/widgets/kernel/qwidget_p.h8
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp4
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 &regi
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 &regi
// 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);
}