Support translucent windows on eglfs
Task-number: QTBUG-39834 Change-Id: I3f6b041c992365d611aa97a41bc37e80b764b78a Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
This commit is contained in:
parent
33e9aeca7f
commit
7fa584254c
@ -67,8 +67,10 @@ static const char fragment_shader150[] =
|
||||
"out vec4 fragcolor;"
|
||||
"uniform sampler2D textureSampler;"
|
||||
"uniform bool swizzle;"
|
||||
"uniform float opacity;"
|
||||
"void main() {"
|
||||
" vec4 tmpFragColor = texture(textureSampler, uv);"
|
||||
" tmpFragColor.a *= opacity;"
|
||||
" fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
|
||||
"}";
|
||||
|
||||
@ -87,8 +89,10 @@ static const char fragment_shader[] =
|
||||
"varying highp vec2 uv;"
|
||||
"uniform sampler2D textureSampler;"
|
||||
"uniform bool swizzle;"
|
||||
"uniform highp float opacity;"
|
||||
"void main() {"
|
||||
" highp vec4 tmpFragColor = texture2D(textureSampler,uv);"
|
||||
" tmpFragColor.a *= opacity;"
|
||||
" gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
|
||||
"}";
|
||||
|
||||
@ -140,6 +144,8 @@ public:
|
||||
, textureTransformUniformPos(0)
|
||||
, swizzle(false)
|
||||
, swizzleOld(false)
|
||||
, opacity(1.0f)
|
||||
, opacityOld(0.0f)
|
||||
, textureMatrixUniformState(User)
|
||||
, vao(new QOpenGLVertexArrayObject())
|
||||
{ }
|
||||
@ -165,6 +171,11 @@ public:
|
||||
program->setUniformValue(swizzleUniformPos, swizzle);
|
||||
swizzleOld = swizzle;
|
||||
}
|
||||
|
||||
if (opacity != opacityOld) {
|
||||
program->setUniformValue(opacityUniformPos, opacity);
|
||||
opacityOld = opacity;
|
||||
}
|
||||
}
|
||||
|
||||
QOpenGLBuffer vertexBuffer;
|
||||
@ -175,8 +186,11 @@ public:
|
||||
GLuint textureCoordAttribPos;
|
||||
GLuint textureTransformUniformPos;
|
||||
GLuint swizzleUniformPos;
|
||||
GLuint opacityUniformPos;
|
||||
bool swizzle;
|
||||
bool swizzleOld;
|
||||
float opacity;
|
||||
float opacityOld;
|
||||
TextureMatrixUniform textureMatrixUniformState;
|
||||
QScopedPointer<QOpenGLVertexArrayObject> vao;
|
||||
};
|
||||
@ -274,6 +288,7 @@ bool QOpenGLTextureBlitter::create()
|
||||
d->textureCoordAttribPos = d->program->attributeLocation("textureCoord");
|
||||
d->textureTransformUniformPos = d->program->uniformLocation("textureTransform");
|
||||
d->swizzleUniformPos = d->program->uniformLocation("swizzle");
|
||||
d->opacityUniformPos = d->program->uniformLocation("opacity");
|
||||
|
||||
d->program->setUniformValue(d->swizzleUniformPos,false);
|
||||
|
||||
@ -329,6 +344,12 @@ void QOpenGLTextureBlitter::setSwizzleRB(bool swizzle)
|
||||
d->swizzle = swizzle;
|
||||
}
|
||||
|
||||
void QOpenGLTextureBlitter::setOpacity(float opacity)
|
||||
{
|
||||
Q_D(QOpenGLTextureBlitter);
|
||||
d->opacity = opacity;
|
||||
}
|
||||
|
||||
void QOpenGLTextureBlitter::blit(GLuint texture,
|
||||
const QMatrix4x4 &targetTransform,
|
||||
Origin sourceOrigin)
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
void release();
|
||||
|
||||
void setSwizzleRB(bool swizzle);
|
||||
void setOpacity(float opacity);
|
||||
|
||||
void blit(GLuint texture, const QMatrix4x4 &targetTransform, Origin sourceOrigin);
|
||||
void blit(GLuint texture, const QMatrix4x4 &targetTransform, const QMatrix3x3 &sourceTransform);
|
||||
|
@ -105,6 +105,29 @@ void QEGLCompositor::renderAll()
|
||||
windows.at(i)->composited();
|
||||
}
|
||||
|
||||
struct BlendStateBinder
|
||||
{
|
||||
BlendStateBinder() : m_blend(false) {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
void set(bool blend) {
|
||||
if (blend != m_blend) {
|
||||
if (blend) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
m_blend = blend;
|
||||
}
|
||||
}
|
||||
~BlendStateBinder() {
|
||||
if (m_blend)
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
bool m_blend;
|
||||
};
|
||||
|
||||
void QEGLCompositor::render(QEGLPlatformWindow *window)
|
||||
{
|
||||
const QPlatformTextureList *textures = window->textures();
|
||||
@ -114,29 +137,37 @@ void QEGLCompositor::render(QEGLPlatformWindow *window)
|
||||
const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size());
|
||||
glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());
|
||||
|
||||
float currentOpacity = 1.0f;
|
||||
BlendStateBinder blend;
|
||||
|
||||
for (int i = 0; i < textures->count(); ++i) {
|
||||
uint textureId = textures->textureId(i);
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i),
|
||||
targetWindowRect);
|
||||
const float opacity = window->window()->opacity();
|
||||
if (opacity != currentOpacity) {
|
||||
currentOpacity = opacity;
|
||||
m_blitter->setOpacity(currentOpacity);
|
||||
}
|
||||
|
||||
if (textures->count() > 1 && i == textures->count() - 1) {
|
||||
// Backingstore for a widget with QOpenGLWidget subwidgets
|
||||
m_blitter->setSwizzleRB(true);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
blend.set(true);
|
||||
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||
glDisable(GL_BLEND);
|
||||
} else if (textures->count() == 1) {
|
||||
// A regular QWidget window
|
||||
m_blitter->setSwizzleRB(true);
|
||||
const bool translucent = window->window()->requestedFormat().alphaBufferSize() > 0;
|
||||
blend.set(translucent);
|
||||
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||
} else {
|
||||
// Texture from an FBO belonging to a QOpenGLWidget
|
||||
m_blitter->setSwizzleRB(false);
|
||||
blend.set(false);
|
||||
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
|
||||
}
|
||||
}
|
||||
|
||||
m_blitter->setOpacity(1.0f);
|
||||
}
|
||||
|
||||
QEGLCompositor *QEGLCompositor::instance()
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include <QtGui/QOpenGLShaderProgram>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
#include "qeglplatformbackingstore_p.h"
|
||||
#include "qeglcompositor_p.h"
|
||||
@ -209,9 +210,16 @@ void QEGLPlatformBackingStore::composited()
|
||||
}
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn)
|
||||
void QEGLPlatformBackingStore::beginPaint(const QRegion ®ion)
|
||||
{
|
||||
m_dirty |= rgn;
|
||||
m_dirty |= region;
|
||||
|
||||
if (m_image.hasAlphaChannel()) {
|
||||
QPainter p(&m_image);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
foreach (const QRect &r, region.rects())
|
||||
p.fillRect(r, Qt::transparent);
|
||||
}
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||
@ -223,7 +231,15 @@ void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticCo
|
||||
if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface))
|
||||
return;
|
||||
|
||||
m_image = QImage(size, QImage::Format_RGB32);
|
||||
// Child windows do not get real native surfaces and so share the same
|
||||
// format as the parent, regardless of what has been requested. The
|
||||
// exception is WA_TranslucentBackground that sets alphaBufferSize in the
|
||||
// requested format, this has to be taken into account when compositing.
|
||||
const bool translucent = m_window->window()->requestedFormat().alphaBufferSize() > 0;
|
||||
const QImage::Format format = translucent ? QImage::Format_RGBA8888 : QImage::Format_RGBX8888;
|
||||
|
||||
m_image = QImage(size, format);
|
||||
|
||||
m_window->create();
|
||||
|
||||
screen->compositingContext()->makeCurrent(dstWin->window());
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
|
||||
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
|
||||
|
||||
void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
|
||||
void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE;
|
||||
|
||||
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE;
|
||||
void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
|
||||
|
@ -127,4 +127,12 @@ WId QEGLPlatformWindow::winId() const
|
||||
return m_winId;
|
||||
}
|
||||
|
||||
void QEGLPlatformWindow::setOpacity(qreal)
|
||||
{
|
||||
if (!isRaster())
|
||||
qWarning("eglfs: Cannot set opacity for non-raster windows");
|
||||
|
||||
// Nothing to do here. The opacity is stored in the QWindow.
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
bool isRaster() const;
|
||||
|
||||
WId winId() const Q_DECL_OVERRIDE;
|
||||
void setOpacity(qreal opacity) Q_DECL_OVERRIDE;
|
||||
|
||||
virtual EGLNativeWindowType eglWindow() const = 0;
|
||||
|
||||
|
@ -82,8 +82,10 @@ void QEglFSWindow::create()
|
||||
// they will be composited onto the root window's surface.
|
||||
QEglFSScreen *screen = this->screen();
|
||||
if (screen->primarySurface() != EGL_NO_SURFACE) {
|
||||
if (isRaster() && screen->compositingWindow())
|
||||
if (isRaster() && screen->compositingWindow()) {
|
||||
m_format = screen->compositingWindow()->format();
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)
|
||||
// We can have either a single OpenGL window or multiple raster windows.
|
||||
|
Loading…
Reference in New Issue
Block a user