From 2c8c0cb33aa8137186e8dde8ecff856a5fbf0c55 Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Wed, 10 Oct 2012 13:13:56 +0100 Subject: [PATCH] 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 Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopengl.h | 1 + src/gui/opengl/qopenglshaderprogram.cpp | 56 +++++++++++++++++++++++-- src/gui/opengl/qopenglshaderprogram.h | 5 ++- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h index 049bb23207..1f99738a9f 100644 --- a/src/gui/opengl/qopengl.h +++ b/src/gui/opengl/qopengl.h @@ -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 diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index 88c9c8008c..a5c98605b4 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -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(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(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; } diff --git a/src/gui/opengl/qopenglshaderprogram.h b/src/gui/opengl/qopenglshaderprogram.h index f371326239..00b67f9434 100644 --- a/src/gui/opengl/qopenglshaderprogram.h +++ b/src/gui/opengl/qopenglshaderprogram.h @@ -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);