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>
This commit is contained in:
parent
931e4ae665
commit
5bb4d06494
@ -61,6 +61,10 @@
|
|||||||
|
|
||||||
const int bubbleNum = 8;
|
const int bubbleNum = 8;
|
||||||
|
|
||||||
|
#ifndef GL_SRGB8_ALPHA8
|
||||||
|
#define GL_SRGB8_ALPHA8 0x8C43
|
||||||
|
#endif
|
||||||
|
|
||||||
GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
|
GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
|
||||||
: m_mainWindow(mw),
|
: m_mainWindow(mw),
|
||||||
m_showBubbles(true),
|
m_showBubbles(true),
|
||||||
@ -75,6 +79,8 @@ GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
|
|||||||
m_background(background)
|
m_background(background)
|
||||||
{
|
{
|
||||||
setMinimumSize(300, 250);
|
setMinimumSize(300, 250);
|
||||||
|
if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
|
||||||
|
setTextureFormat(GL_SRGB8_ALPHA8);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLWidget::~GLWidget()
|
GLWidget::~GLWidget()
|
||||||
|
@ -61,6 +61,8 @@ int main( int argc, char ** argv )
|
|||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
format.setDepthBufferSize(24);
|
format.setDepthBufferSize(24);
|
||||||
format.setStencilBufferSize(8);
|
format.setStencilBufferSize(8);
|
||||||
|
if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
|
||||||
|
format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
|
||||||
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
|
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
|
||||||
format.setSamples(4);
|
format.setSamples(4);
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
|
@ -566,7 +566,8 @@ public:
|
|||||||
paintDevice(0),
|
paintDevice(0),
|
||||||
updateBehavior(QOpenGLWidget::NoPartialUpdate),
|
updateBehavior(QOpenGLWidget::NoPartialUpdate),
|
||||||
requestedSamples(0),
|
requestedSamples(0),
|
||||||
inPaintGL(false)
|
inPaintGL(false),
|
||||||
|
textureFormat(0)
|
||||||
{
|
{
|
||||||
requestedFormat = QSurfaceFormat::defaultFormat();
|
requestedFormat = QSurfaceFormat::defaultFormat();
|
||||||
}
|
}
|
||||||
@ -610,6 +611,7 @@ public:
|
|||||||
QOpenGLWidget::UpdateBehavior updateBehavior;
|
QOpenGLWidget::UpdateBehavior updateBehavior;
|
||||||
int requestedSamples;
|
int requestedSamples;
|
||||||
bool inPaintGL;
|
bool inPaintGL;
|
||||||
|
GLenum textureFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
void QOpenGLWidgetPaintDevicePrivate::beginPaint()
|
void QOpenGLWidgetPaintDevicePrivate::beginPaint()
|
||||||
@ -703,12 +705,16 @@ void QOpenGLWidgetPrivate::recreateFbo()
|
|||||||
QOpenGLFramebufferObjectFormat format;
|
QOpenGLFramebufferObjectFormat format;
|
||||||
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
||||||
format.setSamples(samples);
|
format.setSamples(samples);
|
||||||
|
if (textureFormat)
|
||||||
|
format.setInternalTextureFormat(textureFormat);
|
||||||
|
|
||||||
const QSize deviceSize = q->size() * q->devicePixelRatioF();
|
const QSize deviceSize = q->size() * q->devicePixelRatioF();
|
||||||
fbo = new QOpenGLFramebufferObject(deviceSize, format);
|
fbo = new QOpenGLFramebufferObject(deviceSize, format);
|
||||||
if (samples > 0)
|
if (samples > 0)
|
||||||
resolvedFbo = new QOpenGLFramebufferObject(deviceSize);
|
resolvedFbo = new QOpenGLFramebufferObject(deviceSize);
|
||||||
|
|
||||||
|
textureFormat = fbo->format().internalTextureFormat();
|
||||||
|
|
||||||
fbo->bind();
|
fbo->bind();
|
||||||
context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
@ -767,7 +773,9 @@ void QOpenGLWidgetPrivate::initialize()
|
|||||||
return;
|
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();
|
QSurfaceFormat tlwFormat = tlw->windowHandle()->format();
|
||||||
if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
|
if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
|
||||||
// Most platforms will pick up the changed swap interval on the next
|
// 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)
|
void QOpenGLWidget::setFormat(const QSurfaceFormat &format)
|
||||||
{
|
{
|
||||||
Q_UNUSED(format);
|
|
||||||
Q_D(QOpenGLWidget);
|
Q_D(QOpenGLWidget);
|
||||||
if (Q_UNLIKELY(d->initialized)) {
|
if (Q_UNLIKELY(d->initialized)) {
|
||||||
qWarning("QOpenGLWidget: Already initialized, setting the format has no effect");
|
qWarning("QOpenGLWidget: Already initialized, setting the format has no effect");
|
||||||
@ -1022,6 +1029,47 @@ QSurfaceFormat QOpenGLWidget::format() const
|
|||||||
return d->initialized ? d->context->format() : d->requestedFormat;
|
return d->initialized ? d->context->format() : d->requestedFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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
|
\return \e true if the widget and OpenGL resources, like the context, have
|
||||||
been successfully initialized. Note that the return value is always false
|
been successfully initialized. Note that the return value is always false
|
||||||
|
@ -72,6 +72,9 @@ public:
|
|||||||
void setFormat(const QSurfaceFormat &format);
|
void setFormat(const QSurfaceFormat &format);
|
||||||
QSurfaceFormat format() const;
|
QSurfaceFormat format() const;
|
||||||
|
|
||||||
|
GLenum textureFormat() const;
|
||||||
|
void setTextureFormat(GLenum texFormat);
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
void makeCurrent();
|
void makeCurrent();
|
||||||
|
@ -64,6 +64,7 @@ void tst_QOpenGLWidget::create()
|
|||||||
{
|
{
|
||||||
QScopedPointer<QOpenGLWidget> w(new QOpenGLWidget);
|
QScopedPointer<QOpenGLWidget> w(new QOpenGLWidget);
|
||||||
QVERIFY(!w->isValid());
|
QVERIFY(!w->isValid());
|
||||||
|
QVERIFY(w->textureFormat() == 0);
|
||||||
QSignalSpy frameSwappedSpy(w.data(), SIGNAL(frameSwapped()));
|
QSignalSpy frameSwappedSpy(w.data(), SIGNAL(frameSwapped()));
|
||||||
w->show();
|
w->show();
|
||||||
QTest::qWaitForWindowExposed(w.data());
|
QTest::qWaitForWindowExposed(w.data());
|
||||||
@ -73,6 +74,7 @@ void tst_QOpenGLWidget::create()
|
|||||||
QVERIFY(w->context());
|
QVERIFY(w->context());
|
||||||
QCOMPARE(w->context()->format(), w->format());
|
QCOMPARE(w->context()->format(), w->format());
|
||||||
QVERIFY(w->defaultFramebufferObject() != 0);
|
QVERIFY(w->defaultFramebufferObject() != 0);
|
||||||
|
QVERIFY(w->textureFormat() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClearWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
class ClearWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
||||||
|
Loading…
x
Reference in New Issue
Block a user