OpenGL: Reinstate support for OpenGL geometry shaders

Unlike QGLShader, this requires the OpenGL 3.2 core implementation
of geometry shaders to keep the API simple.

Change-Id: Icb07f430c4c5b5d950bcf6f7119becec4cfaad8a
Reviewed-by: James Turner <james.turner@kdab.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
Sean Harmer 2012-10-10 13:13:56 +01:00 committed by The Qt Project
parent 05a61de622
commit 2c8c0cb33a
3 changed files with 58 additions and 4 deletions

View File

@ -103,6 +103,7 @@ typedef GLfloat GLdouble;
#if !defined(QT_OPENGL_ES_2)
# if !defined(Q_OS_MAC) || (defined(Q_OS_MAC) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
# define QT_OPENGL_3
# define QT_OPENGL_3_2
# endif
#endif

View File

@ -145,6 +145,8 @@ QT_BEGIN_NAMESPACE
\value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
\value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
\value Geometry Geometry shaders written in the OpenGL Shading Language (GLSL)
based on the OpenGL core feature (requires OpenGL >= 3.2).
*/
class QOpenGLShaderPrivate : public QObjectPrivate
@ -156,7 +158,17 @@ public:
, shaderType(type)
, compiled(false)
, glfuncs(new QOpenGLFunctions(ctx))
#ifndef QT_OPENGL_ES_2
, supportsGeometryShaders(false)
#endif
{
#ifndef QT_OPENGL_ES_2
// Geometry shaders require OpenGL >= 3.2
if (shaderType & QOpenGLShader::Geometry) {
QSurfaceFormat f = ctx->format();
supportsGeometryShaders = (f.version() >= qMakePair<int, int>(3, 2));
}
#endif
}
~QOpenGLShaderPrivate();
@ -167,6 +179,11 @@ public:
QOpenGLFunctions *glfuncs;
#ifndef QT_OPENGL_ES_2
// Support for geometry shaders
bool supportsGeometryShaders;
#endif
bool create();
bool compile(QOpenGLShader *q);
void deleteShader();
@ -192,10 +209,15 @@ bool QOpenGLShaderPrivate::create()
if (!context)
return false;
GLuint shader;
if (shaderType == QOpenGLShader::Vertex)
if (shaderType == QOpenGLShader::Vertex) {
shader = glfuncs->glCreateShader(GL_VERTEX_SHADER);
else
#if defined(QT_OPENGL_3_2)
} else if (shaderType == QOpenGLShader::Geometry && supportsGeometryShaders) {
shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER);
#endif
} else {
shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
}
if (!shader) {
qWarning() << "QOpenGLShader: could not create shader";
return false;
@ -234,6 +256,8 @@ bool QOpenGLShaderPrivate::compile(QOpenGLShader *q)
type = types[0];
else if (shaderType == QOpenGLShader::Vertex)
type = types[1];
else if (shaderType == QOpenGLShader::Geometry)
type = types[2];
// Get info and source code lengths
GLint infoLogLength = 0;
@ -2926,6 +2950,19 @@ void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4
setUniformValueArray(uniformLocation(name), values, count);
}
/*!
Returns the hardware limit for how many vertices a geometry shader
can output.
*/
int QOpenGLShaderProgram::maxGeometryOutputVertices() const
{
GLint n = 0;
#if defined(QT_OPENGL_3_2)
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &n);
#endif
return n;
}
/*!
Returns true if shader programs written in the OpenGL Shading
Language (GLSL) are supported on this system; false otherwise.
@ -2972,9 +3009,22 @@ bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context)
if (!context)
return false;
if ((type & ~(Vertex | Fragment)) || type == 0)
if ((type & ~(Geometry | Vertex | Fragment)) || type == 0)
return false;
if (type == Geometry) {
#ifndef QT_OPENGL_ES_2
// Geometry shaders require OpenGL 3.2 or newer
QSurfaceFormat format = context->format();
return (format.version() >= qMakePair<int, int>(3, 2));
#else
// No geometry shader support in OpenGL ES2
return false;
#endif
}
// Unconditional support of vertex and fragment shaders implicitly assumes
// a minimum OpenGL version of 2.0
return true;
}

View File

@ -64,7 +64,8 @@ public:
enum ShaderTypeBit
{
Vertex = 0x0001,
Fragment = 0x0002
Fragment = 0x0002,
Geometry = 0x0004
};
Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit)
@ -126,6 +127,8 @@ public:
GLuint programId() const;
int maxGeometryOutputVertices() const;
void bindAttributeLocation(const char *name, int location);
void bindAttributeLocation(const QByteArray& name, int location);
void bindAttributeLocation(const QString& name, int location);