summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2022-09-02 14:11:18 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2022-09-14 14:25:38 +0200
commit72dd23cf53e910a0e34e71c9a7bf94f92c91fd7d (patch)
tree0af7ebd612b40821497d448322c51f526c7d7eb8 /src/opengl
parent8d7d210aa59f4c6e7d370ec7b1fdee6dd8f15324 (diff)
Defer creating the special shaders in the texture blitter
Port of the 5.15 change. It is not strictly required for Qt 6 since the immediate problem of failing to compile some of the shaders with some drivers will pop up much more rarely in practice, because neither Multimedia nor the backing store compositor for QOpenGLWidget/QQuickWidget use QOpenGLTextureBlitter in 6.4 and newer. To maintain the internal behavior between 5 and 6, the patch is nonetheless ported to Qt 6. It also has a performance benefit for the users of the blitter, because now the special shader variants (for rectangle or external textures) are only created when needed. Task-number: QTBUG-101396 Change-Id: I1cf4bec0c74045f4b6f94765563254026bf0b7d8 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/qopengltextureblitter.cpp75
1 files changed, 57 insertions, 18 deletions
diff --git a/src/opengl/qopengltextureblitter.cpp b/src/opengl/qopengltextureblitter.cpp
index 664aa5e11b..2b43afc3b6 100644
--- a/src/opengl/qopengltextureblitter.cpp
+++ b/src/opengl/qopengltextureblitter.cpp
@@ -200,7 +200,8 @@ public:
TEXTURE_RECTANGLE
};
- QOpenGLTextureBlitterPrivate() :
+ QOpenGLTextureBlitterPrivate(QOpenGLTextureBlitter *q_ptr) :
+ q(q_ptr),
swizzle(false),
opacity(1.0f),
vao(new QOpenGLVertexArrayObject),
@@ -208,14 +209,16 @@ 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);
+ QOpenGLTextureBlitter *q;
QOpenGLBuffer vertexBuffer;
QOpenGLBuffer textureBuffer;
struct Program {
@@ -262,9 +265,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);
@@ -287,6 +294,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
@@ -311,7 +320,8 @@ void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
const QMatrix3x3 &sourceTransform)
{
TextureBinder binder(currentTarget, texture);
- prepareProgram(targetTransform);
+ if (!prepareProgram(targetTransform))
+ return;
Program *program = &programs[targetToProgramIndex(currentTarget)];
@@ -327,7 +337,8 @@ void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
QOpenGLTextureBlitter::Origin origin)
{
TextureBinder binder(currentTarget, texture);
- prepareProgram(targetTransform);
+ if (!prepareProgram(targetTransform))
+ return;
Program *program = &programs[targetToProgramIndex(currentTarget)];
@@ -380,6 +391,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 && q->supportsRectangleTarget()) {
+ if (!buildProgram(idx, vertex_shader150, fragment_shader150_rectangle))
+ return false;
+ }
+ } else {
+ if (idx == QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE && q->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.isNull();
+}
+
/*!
Constructs a new QOpenGLTextureBlitter instance.
@@ -390,7 +430,7 @@ bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs
create().
*/
QOpenGLTextureBlitter::QOpenGLTextureBlitter()
- : d_ptr(new QOpenGLTextureBlitterPrivate)
+ : d_ptr(new QOpenGLTextureBlitterPrivate(this))
{
}
@@ -430,21 +470,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 (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 (supportsRectangleTarget())
- if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_RECTANGLE, vertex_shader, fragment_shader_rectangle))
- return false;
}
// Create and bind the VAO, if supported.
@@ -553,7 +586,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();
@@ -575,7 +612,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();
}