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>bb10
parent
5bb4d06494
commit
f9f9bea370
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue