Fix up QOpenGLWidget transparency support
The glColorMask call was troublesome. In addition, the Qt::WA_TranslucentBackground was misinterpreted and recommended misleadingly in the documentation. The hellogl2 example's --transparent argument was disfunctional in practice. Replace glColorMask with glBlendFuncSeparate. The hellogl2 example and the docs are now corrected wrt enabling semi-transparency in a QOpenGLWidget that is not a top-level (which is the most common case). Task-number: QTBUG-47276 Change-Id: I6f40e732d455f5efcf158649ac9a52ff9f240e85 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
This commit is contained in:
parent
bf2c9fd2fd
commit
b46ffbca0c
@ -55,8 +55,11 @@ GLWidget::GLWidget(QWidget *parent)
|
|||||||
// --transparent causes the clear color to be transparent. Therefore, on systems that
|
// --transparent causes the clear color to be transparent. Therefore, on systems that
|
||||||
// support it, the widget will become transparent apart from the logo.
|
// support it, the widget will become transparent apart from the logo.
|
||||||
m_transparent = QCoreApplication::arguments().contains(QStringLiteral("--transparent"));
|
m_transparent = QCoreApplication::arguments().contains(QStringLiteral("--transparent"));
|
||||||
if (m_transparent)
|
if (m_transparent) {
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
QSurfaceFormat fmt = format();
|
||||||
|
fmt.setAlphaBufferSize(8);
|
||||||
|
setFormat(fmt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLWidget::~GLWidget()
|
GLWidget::~GLWidget()
|
||||||
|
@ -59,6 +59,10 @@ int main(int argc, char *argv[])
|
|||||||
QSurfaceFormat::setDefaultFormat(fmt);
|
QSurfaceFormat::setDefaultFormat(fmt);
|
||||||
|
|
||||||
MainWindow mainWindow;
|
MainWindow mainWindow;
|
||||||
|
if (QCoreApplication::arguments().contains(QStringLiteral("--transparent"))) {
|
||||||
|
mainWindow.setAttribute(Qt::WA_TranslucentBackground);
|
||||||
|
mainWindow.setAttribute(Qt::WA_NoSystemBackground, false);
|
||||||
|
}
|
||||||
mainWindow.resize(mainWindow.sizeHint());
|
mainWindow.resize(mainWindow.sizeHint());
|
||||||
int desktopArea = QApplication::desktop()->width() *
|
int desktopArea = QApplication::desktop()->width() *
|
||||||
QApplication::desktop()->height();
|
QApplication::desktop()->height();
|
||||||
|
@ -300,11 +300,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i
|
|||||||
}
|
}
|
||||||
|
|
||||||
funcs->glEnable(GL_BLEND);
|
funcs->glEnable(GL_BLEND);
|
||||||
funcs->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
|
||||||
// Do not write out alpha. We need blending, but only for RGB. The toplevel may have
|
|
||||||
// alpha enabled in which case blending (writing out < 1.0 alpha values) would lead to
|
|
||||||
// semi-transparency even when it is not wanted.
|
|
||||||
funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
|
||||||
|
|
||||||
// Backingstore texture with the normal widgets.
|
// Backingstore texture with the normal widgets.
|
||||||
GLuint textureId = 0;
|
GLuint textureId = 0;
|
||||||
@ -364,7 +360,6 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i
|
|||||||
blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
|
blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
||||||
funcs->glDisable(GL_BLEND);
|
funcs->glDisable(GL_BLEND);
|
||||||
d_ptr->blitter->release();
|
d_ptr->blitter->release();
|
||||||
|
|
||||||
|
@ -425,7 +425,12 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
Note that this does not apply when there are no other widgets underneath and
|
Note that this does not apply when there are no other widgets underneath and
|
||||||
the intention is to have a semi-transparent window. In that case the
|
the intention is to have a semi-transparent window. In that case the
|
||||||
traditional approach of setting Qt::WA_TranslucentBackground is sufficient.
|
traditional approach of setting Qt::WA_TranslucentBackground
|
||||||
|
on the top-level window is sufficient. Note that if the transparent areas are
|
||||||
|
only desired in the QOpenGLWidget, then Qt::WA_NoSystemBackground will need
|
||||||
|
to be turned back to \c false after enabling Qt::WA_TranslucentBackground.
|
||||||
|
Additionally, requesting an alpha channel for the QOpenGLWidget's context via
|
||||||
|
setFormat() may be necessary too, depending on the system.
|
||||||
|
|
||||||
QOpenGLWidget supports multiple update behaviors, just like QOpenGLWindow. In
|
QOpenGLWidget supports multiple update behaviors, just like QOpenGLWindow. In
|
||||||
preserved mode the rendered content from the previous paintGL() call is
|
preserved mode the rendered content from the previous paintGL() call is
|
||||||
@ -607,7 +612,7 @@ void QOpenGLWidgetPaintDevicePrivate::beginPaint()
|
|||||||
// with the palette's background color.
|
// with the palette's background color.
|
||||||
if (w->autoFillBackground()) {
|
if (w->autoFillBackground()) {
|
||||||
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
||||||
if (w->testAttribute(Qt::WA_TranslucentBackground)) {
|
if (w->format().hasAlpha()) {
|
||||||
f->glClearColor(0, 0, 0, 0);
|
f->glClearColor(0, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
QColor c = w->palette().brush(w->backgroundRole()).color();
|
QColor c = w->palette().brush(w->backgroundRole()).color();
|
||||||
@ -955,13 +960,12 @@ QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const
|
|||||||
OpenGL widgets, individual calls to this function can be replaced by one single call to
|
OpenGL widgets, individual calls to this function can be replaced by one single call to
|
||||||
QSurfaceFormat::setDefaultFormat() before creating the first widget.
|
QSurfaceFormat::setDefaultFormat() before creating the first widget.
|
||||||
|
|
||||||
\note Requesting an alpha buffer via this function, or by setting
|
\note Requesting an alpha buffer via this function will not lead to the
|
||||||
Qt::WA_TranslucentBackground, will not lead to the desired results when the intention is
|
desired results when the intention is to make other widgets beneath visible.
|
||||||
to make other widgets beneath visible. Instead, use Qt::WA_AlwaysStackOnTop to enable
|
Instead, use Qt::WA_AlwaysStackOnTop to enable semi-transparent QOpenGLWidget
|
||||||
semi-transparent QOpenGLWidget instances with other widgets visible underneath. Keep in
|
instances with other widgets visible underneath. Keep in mind however that
|
||||||
mind however that this breaks the stacking order, so it will no longer be possible to
|
this breaks the stacking order, so it will no longer be possible to have
|
||||||
have other widgets on top of the QOpenGLWidget. When the intention is to have a
|
other widgets on top of the QOpenGLWidget.
|
||||||
semi-transparent top-level window, Qt::WA_TranslucentBackground is sufficient.
|
|
||||||
|
|
||||||
\sa format(), Qt::WA_AlwaysStackOnTop, QSurfaceFormat::setDefaultFormat()
|
\sa format(), Qt::WA_AlwaysStackOnTop, QSurfaceFormat::setDefaultFormat()
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user