From 6b6b206ed8634323570712e003fc159fbf5f8303 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 28 Jan 2010 08:18:34 +1000 Subject: Better support for user-generated binary shaders If the user provided their own shader with glShaderBinary(), QGLShaderProgram::addShader() would refuse to add it because it wasn't marked as "compiled". According to the OpenGL/ES 2.0 specification: "It is permissible to attach a shader object to a program object before source code has been loaded into the shader object or before the shader object has been compiled." Based on this, the compile check has been removed from addShader() which should make supporting binary shaders easier. Similarly, link() and programId() have been modified to support applications that use glProgramBinaryOES() to specify program binaries. Task-number: QTBUG-7490 Reviewed-by: Tom Cooksey --- src/opengl/qglshaderprogram.cpp | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 5e2f1f5..79484fa 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -106,6 +106,19 @@ QT_BEGIN_NAMESPACE \snippet doc/src/snippets/code/src_opengl_qglshaderprogram.cpp 2 + \section1 Binary shaders and programs + + Binary shaders may be specified using \c{glShaderBinary()} on + the return value from QGLShader::shaderId(). The QGLShader instance + containing the binary can then be added to the shader program with + addShader() and linked in the usual fashion with link(). + + Binary programs may be specified using \c{glProgramBinaryOES()} + on the return value from programId(). Then the application should + call link(), which will notice that the program has already been + specified and linked, allowing other operations to be performed + on the shader program. + \sa QGLShader */ @@ -632,8 +645,6 @@ bool QGLShaderProgram::addShader(QGLShader *shader) qWarning("QGLShaderProgram::addShader: Program and shader are not associated with same context."); return false; } - if (!shader->d_func()->compiled) - return false; if (!shader->d_func()->shaderGuard.id()) return false; glAttachShader(d->programGuard.id(), shader->d_func()->shaderGuard.id()); @@ -820,8 +831,20 @@ bool QGLShaderProgram::link() GLuint program = d->programGuard.id(); if (!program) return false; + GLint value; + if (d->shaders.isEmpty()) { + // If there are no explicit shaders, then it is possible that the + // application added a program binary with glProgramBinaryOES(), + // or otherwise populated the shaders itself. Check to see if the + // program is already linked and bail out if so. + value = 0; + glGetProgramiv(program, GL_LINK_STATUS, &value); + d->linked = (value != 0); + if (d->linked) + return true; + } glLinkProgram(program); - GLint value = 0; + value = 0; glGetProgramiv(program, GL_LINK_STATUS, &value); d->linked = (value != 0); value = 0; @@ -928,6 +951,15 @@ void QGLShaderProgram::release() GLuint QGLShaderProgram::programId() const { Q_D(const QGLShaderProgram); + GLuint id = d->programGuard.id(); + if (id) + return id; + + // Create the identifier if we don't have one yet. This is for + // applications that want to create the attached shader configuration + // themselves, particularly those using program binaries. + if (!const_cast(this)->init()) + return 0; return d->programGuard.id(); } -- cgit v0.12