diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-02-20 15:19:49 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-02-26 20:06:07 +0000 |
commit | 5bb4d064945db43d62ea24b5d23bf4b0b4420e38 (patch) | |
tree | c9f01a6beec73a040d03445a4e34b94f4b9e4ddd | |
parent | 931e4ae66504f5d0be9d097565b4e9f49a92c69a (diff) |
Add support for custom texture format in QOpenGLWidget
...in order to support sRGB framebuffers.
Add a --srgb option to the qopenglwidget example to allow testing.
[ChangeLog][QtWidgets][QOpenGLWidget] Added support for specifying
custom internal texture formats in QOpenGLWidget in order to make it
possible to have the widget backed by an sRGB-capable framebuffer.
Task-number: QTBUG-50987
Change-Id: I112e2f0ab0b1478c69e601031aa0bafaa87fa847
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | examples/opengl/qopenglwidget/glwidget.cpp | 6 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/main.cpp | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qopenglwidget.cpp | 54 | ||||
-rw-r--r-- | src/widgets/kernel/qopenglwidget.h | 3 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp | 2 |
5 files changed, 64 insertions, 3 deletions
diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp index 21d922d713..bb7c952a26 100644 --- a/examples/opengl/qopenglwidget/glwidget.cpp +++ b/examples/opengl/qopenglwidget/glwidget.cpp @@ -61,6 +61,10 @@ const int bubbleNum = 8; +#ifndef GL_SRGB8_ALPHA8 +#define GL_SRGB8_ALPHA8 0x8C43 +#endif + GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) : m_mainWindow(mw), m_showBubbles(true), @@ -75,6 +79,8 @@ GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) m_background(background) { setMinimumSize(300, 250); + if (QCoreApplication::arguments().contains(QStringLiteral("--srgb"))) + setTextureFormat(GL_SRGB8_ALPHA8); } GLWidget::~GLWidget() diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp index d7aa791142..f9b5731b8f 100644 --- a/examples/opengl/qopenglwidget/main.cpp +++ b/examples/opengl/qopenglwidget/main.cpp @@ -61,6 +61,8 @@ int main( int argc, char ** argv ) QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); + if (QCoreApplication::arguments().contains(QStringLiteral("--srgb"))) + format.setColorSpace(QSurfaceFormat::sRGBColorSpace); if (QCoreApplication::arguments().contains(QStringLiteral("--multisample"))) format.setSamples(4); QSurfaceFormat::setDefaultFormat(format); diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 147e0774e7..fd45abc8a2 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -566,7 +566,8 @@ public: paintDevice(0), updateBehavior(QOpenGLWidget::NoPartialUpdate), requestedSamples(0), - inPaintGL(false) + inPaintGL(false), + textureFormat(0) { requestedFormat = QSurfaceFormat::defaultFormat(); } @@ -610,6 +611,7 @@ public: QOpenGLWidget::UpdateBehavior updateBehavior; int requestedSamples; bool inPaintGL; + GLenum textureFormat; }; void QOpenGLWidgetPaintDevicePrivate::beginPaint() @@ -703,12 +705,16 @@ void QOpenGLWidgetPrivate::recreateFbo() QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); format.setSamples(samples); + if (textureFormat) + format.setInternalTextureFormat(textureFormat); const QSize deviceSize = q->size() * q->devicePixelRatioF(); fbo = new QOpenGLFramebufferObject(deviceSize, format); if (samples > 0) resolvedFbo = new QOpenGLFramebufferObject(deviceSize); + textureFormat = fbo->format().internalTextureFormat(); + fbo->bind(); context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -767,7 +773,9 @@ void QOpenGLWidgetPrivate::initialize() return; } - // Propagate settings that make sense only for the tlw. + // Propagate settings that make sense only for the tlw. Note that this only + // makes sense for properties that get picked up even after the native + // window is created. QSurfaceFormat tlwFormat = tlw->windowHandle()->format(); if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) { // Most platforms will pick up the changed swap interval on the next @@ -990,7 +998,6 @@ QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const */ void QOpenGLWidget::setFormat(const QSurfaceFormat &format) { - Q_UNUSED(format); Q_D(QOpenGLWidget); if (Q_UNLIKELY(d->initialized)) { qWarning("QOpenGLWidget: Already initialized, setting the format has no effect"); @@ -1023,6 +1030,47 @@ QSurfaceFormat QOpenGLWidget::format() const } /*! + Sets a custom internal texture format. + + When working with sRGB framebuffers, it will be necessary to specify a + format like \c{GL_SRGB8_ALPHA8}. This can be achieved by calling this + function. + + \note This function has no effect if called after the widget has already + been shown and thus it performed initialization. + + \note This function will typically have to be used in combination with a + QSurfaceFormat::setDefaultFormat() call that sets the color space to + QSurfaceFormat::sRGBColorSpace. + + \since 5.10 + */ +void QOpenGLWidget::setTextureFormat(GLenum texFormat) +{ + Q_D(QOpenGLWidget); + if (Q_UNLIKELY(d->initialized)) { + qWarning("QOpenGLWidget: Already initialized, setting the internal texture format has no effect"); + return; + } + + d->textureFormat = texFormat; +} + +/*! + \return the active internal texture format if the widget has already + initialized, the requested format if one was set but the widget has not yet + been made visible, or 0 if setTextureFormat() was not called and the widget + has not yet been made visible. + + \since 5.10 + */ +GLenum QOpenGLWidget::textureFormat() const +{ + Q_D(const QOpenGLWidget); + return d->textureFormat; +} + +/*! \return \e true if the widget and OpenGL resources, like the context, have been successfully initialized. Note that the return value is always false until the widget is shown. diff --git a/src/widgets/kernel/qopenglwidget.h b/src/widgets/kernel/qopenglwidget.h index b60d79bedb..c0a6e41522 100644 --- a/src/widgets/kernel/qopenglwidget.h +++ b/src/widgets/kernel/qopenglwidget.h @@ -72,6 +72,9 @@ public: void setFormat(const QSurfaceFormat &format); QSurfaceFormat format() const; + GLenum textureFormat() const; + void setTextureFormat(GLenum texFormat); + bool isValid() const; void makeCurrent(); diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index e3e26d612f..a1b585d0d3 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -64,6 +64,7 @@ void tst_QOpenGLWidget::create() { QScopedPointer<QOpenGLWidget> w(new QOpenGLWidget); QVERIFY(!w->isValid()); + QVERIFY(w->textureFormat() == 0); QSignalSpy frameSwappedSpy(w.data(), SIGNAL(frameSwapped())); w->show(); QTest::qWaitForWindowExposed(w.data()); @@ -73,6 +74,7 @@ void tst_QOpenGLWidget::create() QVERIFY(w->context()); QCOMPARE(w->context()->format(), w->format()); QVERIFY(w->defaultFramebufferObject() != 0); + QVERIFY(w->textureFormat() != 0); } class ClearWidget : public QOpenGLWidget, protected QOpenGLFunctions |