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(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) # 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
# define QT_OPENGL_3_2
# endif # endif
#endif #endif

View File

@ -145,6 +145,8 @@ QT_BEGIN_NAMESPACE
\value Vertex Vertex shader written in the OpenGL Shading Language (GLSL). \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
\value Fragment Fragment 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 class QOpenGLShaderPrivate : public QObjectPrivate
@ -156,7 +158,17 @@ public:
, shaderType(type) , shaderType(type)
, compiled(false) , compiled(false)
, glfuncs(new QOpenGLFunctions(ctx)) , 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(); ~QOpenGLShaderPrivate();
@ -167,6 +179,11 @@ public:
QOpenGLFunctions *glfuncs; QOpenGLFunctions *glfuncs;
#ifndef QT_OPENGL_ES_2
// Support for geometry shaders
bool supportsGeometryShaders;
#endif
bool create(); bool create();
bool compile(QOpenGLShader *q); bool compile(QOpenGLShader *q);
void deleteShader(); void deleteShader();
@ -192,10 +209,15 @@ bool QOpenGLShaderPrivate::create()
if (!context) if (!context)
return false; return false;
GLuint shader; GLuint shader;
if (shaderType == QOpenGLShader::Vertex) if (shaderType == QOpenGLShader::Vertex) {
shader = glfuncs->glCreateShader(GL_VERTEX_SHADER); 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); shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
}
if (!shader) { if (!shader) {
qWarning() << "QOpenGLShader: could not create shader"; qWarning() << "QOpenGLShader: could not create shader";
return false; return false;
@ -234,6 +256,8 @@ bool QOpenGLShaderPrivate::compile(QOpenGLShader *q)
type = types[0]; type = types[0];
else if (shaderType == QOpenGLShader::Vertex) else if (shaderType == QOpenGLShader::Vertex)
type = types[1]; type = types[1];
else if (shaderType == QOpenGLShader::Geometry)
type = types[2];
// Get info and source code lengths // Get info and source code lengths
GLint infoLogLength = 0; GLint infoLogLength = 0;
@ -2926,6 +2950,19 @@ void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4
setUniformValueArray(uniformLocation(name), values, count); 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 Returns true if shader programs written in the OpenGL Shading
Language (GLSL) are supported on this system; false otherwise. Language (GLSL) are supported on this system; false otherwise.
@ -2972,9 +3009,22 @@ bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context)
if (!context) if (!context)
return false; return false;
if ((type & ~(Vertex | Fragment)) || type == 0) if ((type & ~(Geometry | Vertex | Fragment)) || type == 0)
return false; 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; return true;
} }

View File

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