summaryrefslogtreecommitdiffstats
path: root/src/gui/opengl
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2022-09-02 10:07:50 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2022-09-14 10:23:22 +0200
commit5fb20a61c9895c911f95824e68180fa448894180 (patch)
treec4e0d89a60c9af13f12b416f319c6c2ecafe71e6 /src/gui/opengl
parent3dbe047ec3974c580d0d2a28b52d940c6c5964de (diff)
Defer creating the special shaders in the texture blitter
Won't apply as-is to Qt 6, needs a dedicated patch there. The urgency is different there as well, from 6.4 on the blitter is not used at all in the backingstore compositor, so the fact that preparing some of the special shaders fail with some Intel drivers does not matter and won't break applications using QOpenGLWidget or QQuickWidget. Instead of introducing platform specific ifdefs (e.g. only supporting texture rectangles on macOS, which is where it really is used), defer the compilation of the more exotic shader variants. Deferring the compilation of the potentially problematic shaders to a point where they are actually needed has the benefit of not affecting applications that never need those shaders to begin with, i.e. even if the shader would fail to compile it won't be a problem as the shader is never needed in the first place. In addition, this provides a performance improvement to create() because it now only compiles the commonly used shader, not the other two. This way, even if the sampler2DRect-based shader failed to compile, that would not be a problem for an application using a QOpenGLWidget (and so using the blitter internally), because that particular shader is not needed at all for rendering. What exactly fails with certain older (but not that old) Intel drivers, and what "syntax error syntax error" really means remain a mystery, and likely not something we will solve. Fixes: QTBUG-101396 Change-Id: Ic923d51007af503f2749eaae36297ca6647cfa09 Reviewed-by: Andy Nichols <andy.nichols@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/gui/opengl')
-rw-r--r--src/gui/opengl/qopengltextureblitter.cpp76
1 files changed, 58 insertions, 18 deletions
diff --git a/src/gui/opengl/qopengltextureblitter.cpp b/src/gui/opengl/qopengltextureblitter.cpp
index f2816712b7..7ed56fe571 100644
--- a/src/gui/opengl/qopengltextureblitter.cpp
+++ b/src/gui/opengl/qopengltextureblitter.cpp
@@ -236,7 +236,8 @@ public:
TEXTURE_RECTANGLE
};
- QOpenGLTextureBlitterPrivate() :
+ QOpenGLTextureBlitterPrivate(QOpenGLTextureBlitter *q_ptr) :
+ q(q_ptr),
swizzle(false),
opacity(1.0f),
vao(new QOpenGLVertexArrayObject),
@@ -244,16 +245,18 @@ public:
{ }
bool buildProgram(ProgramIndex idx, const char *vs, const char *fs);
+ bool ensureProgram(ProgramIndex idx);
void blit(GLuint texture, const QMatrix4x4 &targetTransform, const QMatrix3x3 &sourceTransform);
void blit(GLuint texture, const QMatrix4x4 &targetTransform, QOpenGLTextureBlitter::Origin origin);
QMatrix3x3 toTextureCoordinates(const QMatrix3x3 &sourceTransform) const;
- void prepareProgram(const QMatrix4x4 &vertexTransform);
+ bool prepareProgram(const QMatrix4x4 &vertexTransform);
bool supportsRectangleTarget() const;
+ QOpenGLTextureBlitter *q;
QOpenGLBuffer vertexBuffer;
QOpenGLBuffer textureBuffer;
struct Program {
@@ -300,9 +303,13 @@ static inline QOpenGLTextureBlitterPrivate::ProgramIndex targetToProgramIndex(GL
}
}
-void QOpenGLTextureBlitterPrivate::prepareProgram(const QMatrix4x4 &vertexTransform)
+bool QOpenGLTextureBlitterPrivate::prepareProgram(const QMatrix4x4 &vertexTransform)
{
- Program *program = &programs[targetToProgramIndex(currentTarget)];
+ ProgramIndex programIndex = targetToProgramIndex(currentTarget);
+ if (!ensureProgram(programIndex))
+ return false;
+
+ Program *program = &programs[programIndex];
vertexBuffer.bind();
program->glProgram->setAttributeBuffer(program->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
@@ -325,6 +332,8 @@ void QOpenGLTextureBlitterPrivate::prepareProgram(const QMatrix4x4 &vertexTransf
program->glProgram->setUniformValue(program->opacityUniformPos, opacity);
program->opacity = opacity;
}
+
+ return true;
}
QMatrix3x3 QOpenGLTextureBlitterPrivate::toTextureCoordinates(const QMatrix3x3 &sourceTransform) const
@@ -349,7 +358,8 @@ void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
const QMatrix3x3 &sourceTransform)
{
TextureBinder binder(currentTarget, texture);
- prepareProgram(targetTransform);
+ if (!prepareProgram(targetTransform))
+ return;
Program *program = &programs[targetToProgramIndex(currentTarget)];
@@ -365,7 +375,8 @@ void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
QOpenGLTextureBlitter::Origin origin)
{
TextureBinder binder(currentTarget, texture);
- prepareProgram(targetTransform);
+ if (!prepareProgram(targetTransform))
+ return;
Program *program = &programs[targetToProgramIndex(currentTarget)];
@@ -398,6 +409,7 @@ bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs
p->glProgram->link();
if (!p->glProgram->isLinked()) {
qWarning() << "Could not link shader program:\n" << p->glProgram->log();
+ p->glProgram.reset();
return false;
}
@@ -418,6 +430,35 @@ bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs
return true;
}
+bool QOpenGLTextureBlitterPrivate::ensureProgram(ProgramIndex idx)
+{
+ if (programs[idx].glProgram)
+ return true;
+
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ if (!currentContext)
+ return false;
+
+ QSurfaceFormat format = currentContext->format();
+ if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= qMakePair(3,2)) {
+ if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE && supportsRectangleTarget()) {
+ if (!buildProgram(idx, vertex_shader150, fragment_shader150_rectangle))
+ return false;
+ }
+ } else {
+ if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE && supportsRectangleTarget()) {
+ if (!buildProgram(idx, vertex_shader, fragment_shader_rectangle))
+ return false;
+ }
+ if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES && q->supportsExternalOESTarget()) {
+ if (!buildProgram(idx, vertex_shader, fragment_shader_external_oes))
+ return false;
+ }
+ }
+
+ return programs[idx].glProgram;
+}
+
/*!
Constructs a new QOpenGLTextureBlitter instance.
@@ -428,7 +469,7 @@ bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs
create().
*/
QOpenGLTextureBlitter::QOpenGLTextureBlitter()
- : d_ptr(new QOpenGLTextureBlitterPrivate)
+ : d_ptr(new QOpenGLTextureBlitterPrivate(this))
{
}
@@ -468,21 +509,14 @@ bool QOpenGLTextureBlitter::create()
return true;
QSurfaceFormat format = currentContext->format();
+ // Build the most common, 2D texture shader variant.
+ // The other special ones are deferred and compiled only when first needed.
if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= qMakePair(3,2)) {
if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader150, fragment_shader150))
return false;
- if (d->supportsRectangleTarget())
- if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE, vertex_shader150, fragment_shader150_rectangle))
- return false;
} else {
if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader, fragment_shader))
return false;
- if (supportsExternalOESTarget())
- if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES, vertex_shader, fragment_shader_external_oes))
- return false;
- if (d->supportsRectangleTarget())
- if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE, vertex_shader, fragment_shader_rectangle))
- return false;
}
// Create and bind the VAO, if supported.
@@ -591,7 +625,11 @@ void QOpenGLTextureBlitter::bind(GLenum target)
d->vao->bind();
d->currentTarget = target;
- QOpenGLTextureBlitterPrivate::Program *p = &d->programs[targetToProgramIndex(target)];
+ QOpenGLTextureBlitterPrivate::ProgramIndex programIndex = targetToProgramIndex(target);
+ if (!d->ensureProgram(programIndex))
+ return;
+
+ QOpenGLTextureBlitterPrivate::Program *p = &d->programs[programIndex];
p->glProgram->bind();
d->vertexBuffer.bind();
@@ -613,7 +651,9 @@ void QOpenGLTextureBlitter::bind(GLenum target)
void QOpenGLTextureBlitter::release()
{
Q_D(QOpenGLTextureBlitter);
- d->programs[targetToProgramIndex(d->currentTarget)].glProgram->release();
+ QOpenGLTextureBlitterPrivate::Program *p = &d->programs[targetToProgramIndex(d->currentTarget)];
+ if (p->glProgram)
+ p->glProgram->release();
if (d->vao->isCreated())
d->vao->release();
}