summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRhys Weatherley <rhys.weatherley@nokia.com>2009-05-01 00:14:58 (GMT)
committerRhys Weatherley <rhys.weatherley@nokia.com>2009-05-01 00:14:58 (GMT)
commit815eb1c4793ffc9d11ec160996350610deb4db7d (patch)
treefe24c022bc2411023f873da882e4fc1b599471c2
parent446085a8b3f22d7e2735b62b4511907e7aaba82a (diff)
parent96e13b0411ed3f4ef8753edafc41503fc9aceb0f (diff)
downloadQt-815eb1c4793ffc9d11ec160996350610deb4db7d.zip
Qt-815eb1c4793ffc9d11ec160996350610deb4db7d.tar.gz
Qt-815eb1c4793ffc9d11ec160996350610deb4db7d.tar.bz2
Merge branch 'shaderprograms' of git@scm.dev.nokia.troll.no:qt/rweathers-shaderprograms into shader-api
Conflicts: src/gui/math3d/math3d.pri src/gui/math3d/qgenericmatrix.cpp src/gui/math3d/qgenericmatrix.h src/gui/math3d/qmatrix4x4.cpp src/gui/math3d/qmatrix4x4.h src/gui/math3d/qquaternion.cpp src/gui/math3d/qquaternion.h src/gui/math3d/qvector2d.cpp src/gui/math3d/qvector2d.h src/gui/math3d/qvector3d.cpp src/gui/math3d/qvector3d.h src/gui/math3d/qvector4d.cpp src/gui/math3d/qvector4d.h src/opengl/opengl.pro tests/auto/math3d/math3d.pro tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp tests/auto/math3d/qquaternion/tst_qquaternion.cpp tests/auto/math3d/qvectornd/tst_qvectornd.cpp tests/auto/math3d/shared/math3dincludes.h
-rw-r--r--demos/boxes/boxes.pro2
-rw-r--r--demos/boxes/glextensions.cpp37
-rw-r--r--demos/boxes/glextensions.h85
-rw-r--r--demos/boxes/glshaders.cpp266
-rw-r--r--demos/boxes/glshaders.h108
-rw-r--r--demos/boxes/scene.cpp102
-rw-r--r--demos/boxes/scene.h11
-rw-r--r--examples/opengl/hellogl_es2/glwidget.cpp391
-rw-r--r--examples/opengl/hellogl_es2/glwidget.h31
-rw-r--r--src/opengl/gl2paintengineex/qglshader_p.h2
-rw-r--r--src/opengl/opengl.pro2
-rw-r--r--src/opengl/qglextensions.cpp174
-rw-r--r--src/opengl/qglextensions_p.h134
-rw-r--r--src/opengl/qglpixmapfilter.cpp172
-rw-r--r--src/opengl/qglpixmapfilter_p.h29
-rw-r--r--src/opengl/qglshaderprogram.cpp2828
-rw-r--r--src/opengl/qglshaderprogram.h285
17 files changed, 3600 insertions, 1059 deletions
diff --git a/demos/boxes/boxes.pro b/demos/boxes/boxes.pro
index 6c1a331..a7b19a3 100644
--- a/demos/boxes/boxes.pro
+++ b/demos/boxes/boxes.pro
@@ -11,7 +11,6 @@ INCLUDEPATH += .
HEADERS += 3rdparty/fbm.h \
glbuffers.h \
glextensions.h \
- glshaders.h \
gltrianglemesh.h \
qtbox.h \
roundedbox.h \
@@ -21,7 +20,6 @@ HEADERS += 3rdparty/fbm.h \
SOURCES += 3rdparty/fbm.c \
glbuffers.cpp \
glextensions.cpp \
- glshaders.cpp \
main.cpp \
qtbox.cpp \
roundedbox.cpp \
diff --git a/demos/boxes/glextensions.cpp b/demos/boxes/glextensions.cpp
index 59256a8..5f168b6 100644
--- a/demos/boxes/glextensions.cpp
+++ b/demos/boxes/glextensions.cpp
@@ -47,23 +47,6 @@ bool GLExtensionFunctions::resolve(const QGLContext *context)
{
bool ok = true;
- RESOLVE_GL_FUNC(CreateShaderObjectARB)
- RESOLVE_GL_FUNC(ShaderSourceARB)
- RESOLVE_GL_FUNC(CompileShaderARB)
- RESOLVE_GL_FUNC(GetObjectParameterivARB)
- RESOLVE_GL_FUNC(DeleteObjectARB)
- RESOLVE_GL_FUNC(GetInfoLogARB)
- RESOLVE_GL_FUNC(CreateProgramObjectARB)
- RESOLVE_GL_FUNC(AttachObjectARB)
- RESOLVE_GL_FUNC(DetachObjectARB)
- RESOLVE_GL_FUNC(LinkProgramARB)
- RESOLVE_GL_FUNC(UseProgramObjectARB)
- RESOLVE_GL_FUNC(GetUniformLocationARB)
- RESOLVE_GL_FUNC(Uniform1iARB)
- RESOLVE_GL_FUNC(Uniform1fARB)
- RESOLVE_GL_FUNC(Uniform4fARB)
- RESOLVE_GL_FUNC(UniformMatrix4fvARB)
-
RESOLVE_GL_FUNC(GenFramebuffersEXT)
RESOLVE_GL_FUNC(GenRenderbuffersEXT)
RESOLVE_GL_FUNC(BindRenderbufferEXT)
@@ -88,26 +71,6 @@ bool GLExtensionFunctions::resolve(const QGLContext *context)
return ok;
}
-bool GLExtensionFunctions::glslSupported() {
- return CreateShaderObjectARB
- && CreateShaderObjectARB
- && ShaderSourceARB
- && CompileShaderARB
- && GetObjectParameterivARB
- && DeleteObjectARB
- && GetInfoLogARB
- && CreateProgramObjectARB
- && AttachObjectARB
- && DetachObjectARB
- && LinkProgramARB
- && UseProgramObjectARB
- && GetUniformLocationARB
- && Uniform1iARB
- && Uniform1fARB
- && Uniform4fARB
- && UniformMatrix4fvARB;
-}
-
bool GLExtensionFunctions::fboSupported() {
return GenFramebuffersEXT
&& GenRenderbuffersEXT
diff --git a/demos/boxes/glextensions.h b/demos/boxes/glextensions.h
index 74617d6..4755532 100644
--- a/demos/boxes/glextensions.h
+++ b/demos/boxes/glextensions.h
@@ -47,23 +47,6 @@
/*
Functions resolved:
-glCreateShaderObjectARB
-glShaderSourceARB
-glCompileShaderARB
-glGetObjectParameterivARB
-glDeleteObjectARB
-glGetInfoLogARB
-glCreateProgramObjectARB
-glAttachObjectARB
-glDetachObjectARB
-glLinkProgramARB
-glUseProgramObjectARB
-glGetUniformLocationARB
-glUniform1iARB
-glUniform1fARB
-glUniform4fARB
-glUniformMatrix4fvARB
-
glGenFramebuffersEXT
glGenRenderbuffersEXT
glBindRenderbufferEXT
@@ -136,39 +119,6 @@ typedef ptrdiff_t GLsizeiptr;
#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
#endif
-#ifndef GL_ARB_vertex_shader
-#define GL_VERTEX_SHADER_ARB 0x8B31
-#endif
-
-#ifndef GL_ARB_fragment_shader
-#define GL_FRAGMENT_SHADER_ARB 0x8B30
-#endif
-
-#ifndef GL_ARB_shader_objects
-typedef char GLcharARB;
-typedef unsigned int GLhandleARB;
-#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
-#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
-#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
-#endif
-
-typedef GLhandleARB (APIENTRY *_glCreateShaderObjectARB) (GLenum);
-typedef void (APIENTRY *_glShaderSourceARB) (GLhandleARB, GLuint, const GLcharARB**, GLint *);
-typedef void (APIENTRY *_glCompileShaderARB) (GLhandleARB);
-typedef void (APIENTRY *_glGetObjectParameterivARB) (GLhandleARB, GLenum, int *);
-typedef void (APIENTRY *_glDeleteObjectARB) (GLhandleARB);
-typedef void (APIENTRY *_glGetInfoLogARB) (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
-typedef GLhandleARB (APIENTRY *_glCreateProgramObjectARB) ();
-typedef void (APIENTRY *_glAttachObjectARB) (GLhandleARB, GLhandleARB);
-typedef void (APIENTRY *_glDetachObjectARB) (GLhandleARB, GLhandleARB);
-typedef void (APIENTRY *_glLinkProgramARB) (GLhandleARB);
-typedef void (APIENTRY *_glUseProgramObjectARB) (GLhandleARB);
-typedef GLint (APIENTRY *_glGetUniformLocationARB) (GLhandleARB, const GLcharARB *);
-typedef void (APIENTRY *_glUniform1iARB) (GLint, GLint);
-typedef void (APIENTRY *_glUniform1fARB) (GLint, GLfloat);
-typedef void (APIENTRY *_glUniform4fARB) (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
-typedef void (APIENTRY *_glUniformMatrix4fvARB) (GLint, GLuint, GLboolean, const GLfloat *);
-
typedef void (APIENTRY *_glGenFramebuffersEXT) (GLsizei, GLuint *);
typedef void (APIENTRY *_glGenRenderbuffersEXT) (GLsizei, GLuint *);
typedef void (APIENTRY *_glBindRenderbufferEXT) (GLenum, GLuint);
@@ -194,27 +144,9 @@ struct GLExtensionFunctions
{
bool resolve(const QGLContext *context);
- bool glslSupported();
bool fboSupported();
bool openGL15Supported(); // the rest: multi-texture, 3D-texture, vertex buffer objects
- _glCreateShaderObjectARB CreateShaderObjectARB;
- _glShaderSourceARB ShaderSourceARB;
- _glCompileShaderARB CompileShaderARB;
- _glGetObjectParameterivARB GetObjectParameterivARB;
- _glDeleteObjectARB DeleteObjectARB;
- _glGetInfoLogARB GetInfoLogARB;
- _glCreateProgramObjectARB CreateProgramObjectARB;
- _glAttachObjectARB AttachObjectARB;
- _glDetachObjectARB DetachObjectARB;
- _glLinkProgramARB LinkProgramARB;
- _glUseProgramObjectARB UseProgramObjectARB;
- _glGetUniformLocationARB GetUniformLocationARB;
- _glUniform1iARB Uniform1iARB;
- _glUniform1fARB Uniform1fARB;
- _glUniform4fARB Uniform4fARB;
- _glUniformMatrix4fvARB UniformMatrix4fvARB;
-
_glGenFramebuffersEXT GenFramebuffersEXT;
_glGenRenderbuffersEXT GenRenderbuffersEXT;
_glBindRenderbufferEXT BindRenderbufferEXT;
@@ -243,23 +175,6 @@ inline GLExtensionFunctions &getGLExtensionFunctions()
return funcs;
}
-#define glCreateShaderObjectARB getGLExtensionFunctions().CreateShaderObjectARB
-#define glShaderSourceARB getGLExtensionFunctions().ShaderSourceARB
-#define glCompileShaderARB getGLExtensionFunctions().CompileShaderARB
-#define glGetObjectParameterivARB getGLExtensionFunctions().GetObjectParameterivARB
-#define glDeleteObjectARB getGLExtensionFunctions().DeleteObjectARB
-#define glGetInfoLogARB getGLExtensionFunctions().GetInfoLogARB
-#define glCreateProgramObjectARB getGLExtensionFunctions().CreateProgramObjectARB
-#define glAttachObjectARB getGLExtensionFunctions().AttachObjectARB
-#define glDetachObjectARB getGLExtensionFunctions().DetachObjectARB
-#define glLinkProgramARB getGLExtensionFunctions().LinkProgramARB
-#define glUseProgramObjectARB getGLExtensionFunctions().UseProgramObjectARB
-#define glGetUniformLocationARB getGLExtensionFunctions().GetUniformLocationARB
-#define glUniform1iARB getGLExtensionFunctions().Uniform1iARB
-#define glUniform1fARB getGLExtensionFunctions().Uniform1fARB
-#define glUniform4fARB getGLExtensionFunctions().Uniform4fARB
-#define glUniformMatrix4fvARB getGLExtensionFunctions().UniformMatrix4fvARB
-
#define glGenFramebuffersEXT getGLExtensionFunctions().GenFramebuffersEXT
#define glGenRenderbuffersEXT getGLExtensionFunctions().GenRenderbuffersEXT
#define glBindRenderbufferEXT getGLExtensionFunctions().BindRenderbufferEXT
diff --git a/demos/boxes/glshaders.cpp b/demos/boxes/glshaders.cpp
deleted file mode 100644
index b6999a8..0000000
--- a/demos/boxes/glshaders.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the demonstration applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "glshaders.h"
-
-#define GLSHADERS_ASSERT_OPENGL(prefix, assertion, returnStatement) \
-if (m_failed || !(assertion)) { \
- if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
- m_failed = true; \
- returnStatement; \
-}
-
-
-GLShader::GLShader(const char *data, int size, GLenum shaderType)
-: m_compileError(false), m_failed(false)
-{
- GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
- glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)
-
- m_shader = glCreateShaderObjectARB(shaderType);
-
- GLint glSize = size;
- glShaderSourceARB(m_shader, 1, &data, &glSize);
- glCompileShaderARB(m_shader);
- int status;
- glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
- m_compileError = (status != 1);
-}
-
-GLShader::GLShader(const QString& fileName, GLenum shaderType)
- : m_compileError(false), m_failed(false)
-{
- GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
- glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)
-
- m_shader = glCreateShaderObjectARB(shaderType);
-
- QFile file(fileName);
- if (file.open(QIODevice::ReadOnly)) {
- QByteArray bytes = file.readAll();
- GLint size = file.size();
- const char *p = bytes.data();
- file.close();
- glShaderSourceARB(m_shader, 1, &p, &size);
- glCompileShaderARB(m_shader);
- int status;
- glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
- m_compileError = (status != 1);
- } else {
- m_compileError = true;
- }
-}
-
-GLShader::~GLShader()
-{
- GLSHADERS_ASSERT_OPENGL("GLShader::~GLShader", glDeleteObjectARB, return)
-
- glDeleteObjectARB(m_shader);
-}
-
-QString GLShader::log()
-{
- GLSHADERS_ASSERT_OPENGL("GLShader::log", glGetObjectParameterivARB
- && glGetInfoLogARB, return QLatin1String("GLSL not supported."))
-
- int length;
- glGetObjectParameterivARB(m_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
- char *log = new char[length + 1];
- GLsizei glLength = length;
- glGetInfoLogARB(m_shader, glLength, &glLength, log);
- log[glLength] = '\0';
- QString result(log);
- delete log;
- return result;
-}
-
-GLVertexShader::GLVertexShader(const char *data, int size) : GLShader(data, size, GL_VERTEX_SHADER_ARB)
-{
-}
-
-GLVertexShader::GLVertexShader(const QString& fileName) : GLShader(fileName, GL_VERTEX_SHADER_ARB)
-{
-}
-
-GLFragmentShader::GLFragmentShader(const char *data, int size) : GLShader(data, size, GL_FRAGMENT_SHADER_ARB)
-{
-}
-
-GLFragmentShader::GLFragmentShader(const QString& fileName) : GLShader(fileName, GL_FRAGMENT_SHADER_ARB)
-{
-}
-
-GLProgram::GLProgram() : m_linked(false), m_linkError(false), m_failed(false)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::GLProgram", glCreateProgramObjectARB, return)
-
- m_program = glCreateProgramObjectARB();
-}
-
-GLProgram::~GLProgram()
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::~GLProgram", glDeleteObjectARB, return)
-
- glDeleteObjectARB(m_program);
-}
-
-void GLProgram::attach(const GLShader &shader)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::attach", glAttachObjectARB, return)
-
- glAttachObjectARB(m_program, shader.m_shader);
- m_linked = m_linkError = false;
-}
-
-void GLProgram::detach(const GLShader &shader)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::detach", glDetachObjectARB, return)
-
- glDetachObjectARB(m_program, shader.m_shader);
- m_linked = m_linkError = false;
-}
-
-bool GLProgram::failed()
-{
- if (m_failed || m_linkError)
- return true;
-
- if (m_linked)
- return false;
-
- GLSHADERS_ASSERT_OPENGL("GLProgram::failed", glLinkProgramARB && glGetObjectParameterivARB, return true)
-
- glLinkProgramARB(m_program);
- int status;
- glGetObjectParameterivARB(m_program, GL_OBJECT_LINK_STATUS_ARB, &status);
- m_linkError = !(m_linked = (status == 1));
- return m_linkError;
-}
-
-QString GLProgram::log()
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::log", glGetObjectParameterivARB && glGetInfoLogARB,
- return QLatin1String("Failed."))
-
- int length;
- glGetObjectParameterivARB(m_program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
- char *log = new char[length + 1];
- GLsizei glLength = length;
- glGetInfoLogARB(m_program, glLength, &glLength, log);
- log[glLength] = '\0';
- QString result(log);
- delete log;
- return result;
-}
-
-void GLProgram::bind()
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)
-
- if (!failed())
- glUseProgramObjectARB(m_program);
-}
-
-void GLProgram::unbind()
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)
-
- glUseProgramObjectARB(0);
-}
-
-bool GLProgram::hasParameter(const QString& name)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::hasParameter", glGetUniformLocationARB, return false)
-
- if (!failed()) {
- QByteArray asciiName = name.toAscii();
- return -1 != glGetUniformLocationARB(m_program, asciiName.data());
- }
- return false;
-}
-
-void GLProgram::setInt(const QString& name, int value)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::setInt", glGetUniformLocationARB && glUniform1iARB, return)
-
- if (!failed()) {
- QByteArray asciiName = name.toAscii();
- int loc = glGetUniformLocationARB(m_program, asciiName.data());
- glUniform1iARB(loc, value);
- }
-}
-
-void GLProgram::setFloat(const QString& name, float value)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::setFloat", glGetUniformLocationARB && glUniform1fARB, return)
-
- if (!failed()) {
- QByteArray asciiName = name.toAscii();
- int loc = glGetUniformLocationARB(m_program, asciiName.data());
- glUniform1fARB(loc, value);
- }
-}
-
-void GLProgram::setColor(const QString& name, QRgb value)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::setColor", glGetUniformLocationARB && glUniform4fARB, return)
-
- //qDebug() << "Setting color" << name;
- if (!failed()) {
- QByteArray asciiName = name.toAscii();
- int loc = glGetUniformLocationARB(m_program, asciiName.data());
- //qDebug() << "Location of" << name << "is" << loc;
- QColor color(value);
- glUniform4fARB(loc, color.redF(), color.greenF(), color.blueF(), color.alphaF());
- }
-}
-
-void GLProgram::setMatrix(const QString& name, const gfx::Matrix4x4f &mat)
-{
- GLSHADERS_ASSERT_OPENGL("GLProgram::setMatrix", glGetUniformLocationARB && glUniformMatrix4fvARB, return)
-
- if (!failed()) {
- QByteArray asciiName = name.toAscii();
- int loc = glGetUniformLocationARB(m_program, asciiName.data());
- //qDebug() << "Location of" << name << "is" << loc;
- glUniformMatrix4fvARB(loc, 1, GL_FALSE, mat.bits());
- }
-} \ No newline at end of file
diff --git a/demos/boxes/glshaders.h b/demos/boxes/glshaders.h
deleted file mode 100644
index 2b6209a..0000000
--- a/demos/boxes/glshaders.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the demonstration applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef GLSHADERS_H
-#define GLSHADERS_H
-
-//#include <GL/glew.h>
-#include "glextensions.h"
-
-#include <QtGui>
-#include <QtOpenGL>
-
-#include "vector.h"
-
-class GLShader
-{
-public:
- friend class GLProgram;
- virtual ~GLShader();
- bool failed() const {return m_failed;}
- QString log();
-protected:
- GLShader(const char *data, int size, GLenum shaderType);
- GLShader(const QString& fileName, GLenum shaderType);
-
- GLhandleARB m_shader;
- bool m_compileError;
- bool m_failed;
-};
-
-class GLVertexShader : public GLShader
-{
-public:
- GLVertexShader(const char *data, int size);
- GLVertexShader(const QString& fileName);
-};
-
-class GLFragmentShader : public GLShader
-{
-public:
- GLFragmentShader(const char *data, int size);
- GLFragmentShader(const QString& fileName);
-};
-
-class GLProgram
-{
-public:
- GLProgram();
- ~GLProgram();
- void attach(const GLShader &shader);
- void detach(const GLShader &shader);
- void bind();
- void unbind();
- bool failed();
- QString log();
- bool hasParameter(const QString& name);
- // use program before setting values
- void setInt(const QString& name, int value);
- void setFloat(const QString& name, float value);
- void setColor(const QString& name, QRgb value);
- void setMatrix(const QString& name, const gfx::Matrix4x4f &mat);
- // TODO: add a bunch of set-functions for different types.
-private:
- GLhandleARB m_program;
- bool m_linked;
- bool m_linkError;
- bool m_failed;
-};
-
-#endif
diff --git a/demos/boxes/scene.cpp b/demos/boxes/scene.cpp
index 1040e17..e5aab75 100644
--- a/demos/boxes/scene.cpp
+++ b/demos/boxes/scene.cpp
@@ -531,11 +531,11 @@ Scene::~Scene()
if (texture) delete texture;
if (m_mainCubemap)
delete m_mainCubemap;
- foreach (GLProgram *program, m_programs)
+ foreach (QGLShaderProgram *program, m_programs)
if (program) delete program;
if (m_vertexShader)
delete m_vertexShader;
- foreach (GLFragmentShader *shader, m_fragmentShaders)
+ foreach (QGLShader *shader, m_fragmentShaders)
if (shader) delete shader;
foreach (GLRenderTargetCube *rt, m_cubemaps)
if (rt) delete rt;
@@ -549,16 +549,18 @@ void Scene::initGL()
{
m_box = new GLRoundedBox(0.25f, 1.0f, 10);
- m_vertexShader = new GLVertexShader(":/res/boxes/basic.vsh");
+ m_vertexShader = new QGLShader(":/res/boxes/basic.vsh", QGLShader::VertexShader);
QStringList list;
list << ":/res/boxes/cubemap_posx.jpg" << ":/res/boxes/cubemap_negx.jpg" << ":/res/boxes/cubemap_posy.jpg"
<< ":/res/boxes/cubemap_negy.jpg" << ":/res/boxes/cubemap_posz.jpg" << ":/res/boxes/cubemap_negz.jpg";
m_environment = new GLTextureCube(list, qMin(1024, m_maxTextureSize));
- m_environmentShader = new GLFragmentShader(environmentShaderText, strlen(environmentShaderText));
- m_environmentProgram = new GLProgram;
- m_environmentProgram->attach(*m_vertexShader);
- m_environmentProgram->attach(*m_environmentShader);
+ m_environmentShader = new QGLShader(QGLShader::FragmentShader);
+ m_environmentShader->setSourceCode(environmentShaderText);
+ m_environmentProgram = new QGLShaderProgram;
+ m_environmentProgram->addShader(m_vertexShader);
+ m_environmentProgram->addShader(m_environmentShader);
+ m_environmentProgram->link();
const int NOISE_SIZE = 128; // for a different size, B and BM in fbm.c must also be changed
m_noise = new GLTexture3D(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE);
@@ -610,19 +612,19 @@ void Scene::initGL()
filter = QStringList("*.fsh");
files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable);
foreach (QFileInfo file, files) {
- GLProgram *program = new GLProgram;
- GLFragmentShader* shader = new GLFragmentShader(file.absoluteFilePath());
+ QGLShaderProgram *program = new QGLShaderProgram;
+ QGLShader* shader = new QGLShader(file.absoluteFilePath(), QGLShader::FragmentShader);
// The program does not take ownership over the shaders, so store them in a vector so they can be deleted afterwards.
- program->attach(*m_vertexShader);
- program->attach(*shader);
- if (program->failed()) {
+ program->addShader(m_vertexShader);
+ program->addShader(shader);
+ if (!program->link()) {
qWarning("Failed to compile and link shader program");
qWarning("Vertex shader log:");
- qWarning() << m_vertexShader->log();
+ qWarning() << m_vertexShader->errors();
qWarning() << "Fragment shader log ( file =" << file.absoluteFilePath() << "):";
- qWarning() << shader->log();
+ qWarning() << shader->errors();
qWarning("Shader program log:");
- qWarning() << program->log();
+ qWarning() << program->errors();
delete shader;
delete program;
@@ -633,13 +635,13 @@ void Scene::initGL()
m_programs << program;
m_renderOptions->addShader(file.baseName());
- program->bind();
- m_cubemaps << (program->hasParameter("env") ? new GLRenderTargetCube(qMin(256, m_maxTextureSize)) : 0);
- program->unbind();
+ program->enable();
+ m_cubemaps << ((program->uniformLocation("env") != -1) ? new GLRenderTargetCube(qMin(256, m_maxTextureSize)) : 0);
+ program->disable();
}
if (m_programs.size() == 0)
- m_programs << new GLProgram;
+ m_programs << new QGLShaderProgram;
m_renderOptions->emitParameterChanged();
}
@@ -674,12 +676,12 @@ void Scene::renderBoxes(const gfx::Matrix4x4f &view, int excludeBox)
// Don't render the environment if the environment texture can't be set for the correct sampler.
if (glActiveTexture) {
m_environment->bind();
- m_environmentProgram->bind();
- m_environmentProgram->setInt("tex", 0);
- m_environmentProgram->setInt("env", 1);
- m_environmentProgram->setInt("noise", 2);
+ m_environmentProgram->enable();
+ m_environmentProgram->setUniformValue("tex", 0);
+ m_environmentProgram->setUniformValue("env", 1);
+ m_environmentProgram->setUniformValue("noise", 2);
m_box->draw();
- m_environmentProgram->unbind();
+ m_environmentProgram->disable();
m_environment->unbind();
}
@@ -707,14 +709,18 @@ void Scene::renderBoxes(const gfx::Matrix4x4f &view, int excludeBox)
else
m_environment->bind();
}
- m_programs[i]->bind();
- m_programs[i]->setInt("tex", 0);
- m_programs[i]->setInt("env", 1);
- m_programs[i]->setInt("noise", 2);
- m_programs[i]->setMatrix("view", view);
- m_programs[i]->setMatrix("invView", invView);
+ m_programs[i]->enable();
+ m_programs[i]->setUniformValue("tex", 0);
+ m_programs[i]->setUniformValue("env", 1);
+ m_programs[i]->setUniformValue("noise", 2);
+ QMatrix4x4 mview;
+ QMatrix4x4 minvview;
+ memcpy(mview.data(), view.bits(), sizeof(float) * 16);
+ memcpy(minvview.data(), invView.bits(), sizeof(float) * 16);
+ m_programs[i]->setUniformValue("view", mview);
+ m_programs[i]->setUniformValue("invView", minvview);
m_box->draw();
- m_programs[i]->unbind();
+ m_programs[i]->disable();
if (glActiveTexture) {
if (m_dynamicCubemap && m_cubemaps[i])
@@ -737,14 +743,18 @@ void Scene::renderBoxes(const gfx::Matrix4x4f &view, int excludeBox)
m_environment->bind();
}
- m_programs[m_currentShader]->bind();
- m_programs[m_currentShader]->setInt("tex", 0);
- m_programs[m_currentShader]->setInt("env", 1);
- m_programs[m_currentShader]->setInt("noise", 2);
- m_programs[m_currentShader]->setMatrix("view", view);
- m_programs[m_currentShader]->setMatrix("invView", invView);
+ m_programs[m_currentShader]->enable();
+ m_programs[m_currentShader]->setUniformValue("tex", 0);
+ m_programs[m_currentShader]->setUniformValue("env", 1);
+ m_programs[m_currentShader]->setUniformValue("noise", 2);
+ QMatrix4x4 mview;
+ QMatrix4x4 minvview;
+ memcpy(mview.data(), view.bits(), sizeof(float) * 16);
+ memcpy(minvview.data(), invView.bits(), sizeof(float) * 16);
+ m_programs[m_currentShader]->setUniformValue("view", mview);
+ m_programs[m_currentShader]->setUniformValue("invView", minvview);
m_box->draw();
- m_programs[m_currentShader]->unbind();
+ m_programs[m_currentShader]->disable();
if (glActiveTexture) {
if (m_dynamicCubemap)
@@ -1021,20 +1031,20 @@ void Scene::toggleDynamicCubemap(int state)
void Scene::setColorParameter(const QString &name, QRgb color)
{
// set the color in all programs
- foreach (GLProgram *program, m_programs) {
- program->bind();
- program->setColor(name, color);
- program->unbind();
+ foreach (QGLShaderProgram *program, m_programs) {
+ program->enable();
+ program->setUniformValue(program->uniformLocation(name), QColor(color));
+ program->disable();
}
}
void Scene::setFloatParameter(const QString &name, float value)
{
// set the color in all programs
- foreach (GLProgram *program, m_programs) {
- program->bind();
- program->setFloat(name, value);
- program->unbind();
+ foreach (QGLShaderProgram *program, m_programs) {
+ program->enable();
+ program->setUniformValue(program->uniformLocation(name), value);
+ program->disable();
}
}
diff --git a/demos/boxes/scene.h b/demos/boxes/scene.h
index 2db9317..c056739 100644
--- a/demos/boxes/scene.h
+++ b/demos/boxes/scene.h
@@ -53,7 +53,6 @@
#include "vector.h"
#include "trackball.h"
#include "glbuffers.h"
-#include "glshaders.h"
#include "qtbox.h"
#define PI 3.14159265358979
@@ -231,11 +230,11 @@ private:
GLTexture3D *m_noise;
GLRenderTargetCube *m_mainCubemap;
QVector<GLRenderTargetCube *> m_cubemaps;
- QVector<GLProgram *> m_programs;
- GLVertexShader *m_vertexShader;
- QVector<GLFragmentShader *> m_fragmentShaders;
- GLFragmentShader *m_environmentShader;
- GLProgram *m_environmentProgram;
+ QVector<QGLShaderProgram *> m_programs;
+ QGLShader *m_vertexShader;
+ QVector<QGLShader *> m_fragmentShaders;
+ QGLShader *m_environmentShader;
+ QGLShaderProgram *m_environmentProgram;
};
diff --git a/examples/opengl/hellogl_es2/glwidget.cpp b/examples/opengl/hellogl_es2/glwidget.cpp
index 213c5b2..ee50670 100644
--- a/examples/opengl/hellogl_es2/glwidget.cpp
+++ b/examples/opengl/hellogl_es2/glwidget.cpp
@@ -48,124 +48,10 @@
const int bubbleNum = 8;
-inline void CrossProduct(qreal &xOut, qreal &yOut, qreal &zOut, qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2)
-{
- xOut = y1 * z2 - z1 * y2;
- yOut = z1 * x2 - x1 * z2;
- zOut = x1 * y2 - y1 * x2;
-}
-
-inline void Normalize(qreal &x, qreal &y, qreal &z)
-{
- qreal l = sqrt(x*x + y*y + z*z);
- x = x / l;
- y = y / l;
- z = z / l;
-}
-
-inline void IdentityMatrix(GLfloat *m)
-{
- m[0 * 4 + 0] = 1.0f;
- m[1 * 4 + 0] = 0.0f;
- m[2 * 4 + 0] = 0.0f;
- m[3 * 4 + 0] = 0.0f;
- m[0 * 4 + 1] = 0.0f;
- m[1 * 4 + 1] = 1.0f;
- m[2 * 4 + 1] = 0.0f;
- m[3 * 4 + 1] = 0.0f;
- m[0 * 4 + 2] = 0.0f;
- m[1 * 4 + 2] = 0.0f;
- m[2 * 4 + 2] = 1.0f;
- m[3 * 4 + 2] = 0.0f;
- m[0 * 4 + 3] = 0.0f;
- m[1 * 4 + 3] = 0.0f;
- m[2 * 4 + 3] = 0.0f;
- m[3 * 4 + 3] = 1.0f;
-}
-
-// Adjust a 4x4 matrix to apply a scale.
-inline void ScaleMatrix(GLfloat *m, GLfloat scalex, GLfloat scaley, GLfloat scalez)
-{
- m[0 * 4 + 0] *= scalex;
- m[0 * 4 + 1] *= scalex;
- m[0 * 4 + 2] *= scalex;
- m[0 * 4 + 3] *= scalex;
- m[1 * 4 + 0] *= scaley;
- m[1 * 4 + 1] *= scaley;
- m[1 * 4 + 2] *= scaley;
- m[1 * 4 + 3] *= scaley;
- m[2 * 4 + 0] *= scalez;
- m[2 * 4 + 1] *= scalez;
- m[2 * 4 + 2] *= scalez;
- m[2 * 4 + 3] *= scalez;
-}
-
-// Adjust a 4x4 matrix to apply a translation.
-inline void TranslateMatrix(GLfloat *m, GLfloat translatex, GLfloat translatey, GLfloat translatez)
-{
- m[3 * 4 + 0] += m[0 * 4 + 0] * translatex + m[1 * 4 + 0] * translatey + m[2 * 4 + 0] * translatez;
- m[3 * 4 + 1] += m[0 * 4 + 1] * translatex + m[1 * 4 + 1] * translatey + m[2 * 4 + 1] * translatez;
- m[3 * 4 + 2] += m[0 * 4 + 2] * translatex + m[1 * 4 + 2] * translatey + m[2 * 4 + 2] * translatez;
- m[3 * 4 + 3] += m[0 * 4 + 3] * translatex + m[1 * 4 + 3] * translatey + m[2 * 4 + 3] * translatez;
-}
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-// Adjust a 4x4 matrix to apply a rotation.
-inline void RotateMatrix(GLfloat *m, GLfloat angle, GLfloat vx, GLfloat vy, GLfloat vz)
-{
- GLfloat len = sqrt(vx * vx + vy * vy + vz * vz);
- if (len != 0) {
- vx /= len;
- vy /= len;
- vz /= len;
- }
-
- GLfloat c, s, ic;
- c = cos(angle * M_PI / 180.0);
- s = sin(angle * M_PI / 180.0);
- ic = 1.0f - c;
-
- GLfloat rot[16];
- rot[0 * 4 + 0] = vx * vx * ic + c;
- rot[1 * 4 + 0] = vx * vy * ic - vz * s;
- rot[2 * 4 + 0] = vx * vz * ic + vy * s;
- rot[3 * 4 + 0] = 0.0f;
- rot[0 * 4 + 1] = vy * vx * ic + vz * s;
- rot[1 * 4 + 1] = vy * vy * ic + c;
- rot[2 * 4 + 1] = vy * vz * ic - vx * s;
- rot[3 * 4 + 1] = 0.0f;
- rot[0 * 4 + 2] = vx * vz * ic - vy * s;
- rot[1 * 4 + 2] = vy * vz * ic + vx * s;
- rot[2 * 4 + 2] = vz * vz * ic + c;
- rot[3 * 4 + 2] = 0.0f;
- rot[0 * 4 + 3] = 0.0f;
- rot[1 * 4 + 3] = 0.0f;
- rot[2 * 4 + 3] = 0.0f;
- rot[3 * 4 + 3] = 1.0f;
-
- GLfloat temp[16];
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 4; ++j) {
- temp[j * 4 + i] = 0.0f;
- for (int k = 0; k < 4; ++k) {
- temp[j * 4 + i] += m[k * 4 + i] * rot[j * 4 + k];
- }
- }
- }
-
- qMemCopy(m, temp, sizeof(temp));
-}
-
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent)
{
qtLogo = true;
- createdVertices = 0;
- createdNormals = 0;
- m_vertexNumber = 0;
frames = 0;
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
@@ -178,10 +64,6 @@ GLWidget::GLWidget(QWidget *parent)
GLWidget::~GLWidget()
{
- if (createdVertices)
- delete[] createdVertices;
- if (createdNormals)
- delete[] createdNormals;
}
void GLWidget::setScaling(int scale) {
@@ -210,13 +92,11 @@ void GLWidget::showBubbles(bool bubbles)
void GLWidget::paintQtLogo()
{
glDisable(GL_TEXTURE_2D);
- glVertexAttribPointer(vertexAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdVertices);
- glEnableVertexAttribArray(vertexAttr1);
- glVertexAttribPointer(normalAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdNormals);
- glEnableVertexAttribArray(normalAttr1);
- glDrawArrays(GL_TRIANGLES, 0, m_vertexNumber / 3);
- glDisableVertexAttribArray(normalAttr1);
- glDisableVertexAttribArray(vertexAttr1);
+ program1.setAttributeArray(vertexAttr1, vertices.constData());
+ program1.setAttributeArray(normalAttr1, normals.constData());
+ glDrawArrays(GL_TRIANGLES, 0, vertices.size());
+ program1.disableAttributeArray(normalAttr1);
+ program1.disableAttributeArray(vertexAttr1);
}
void GLWidget::paintTexturedCube()
@@ -239,8 +119,7 @@ void GLWidget::paintTexturedCube()
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5
};
- glVertexAttribPointer(vertexAttr2, 3, GL_FLOAT, GL_FALSE, 0, afVertices);
- glEnableVertexAttribArray(vertexAttr2);
+ program2.setAttributeArray(vertexAttr2, afVertices, 3);
GLfloat afTexCoord[] = {
0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
@@ -258,8 +137,7 @@ void GLWidget::paintTexturedCube()
1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f,
0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f
};
- glVertexAttribPointer(texCoordAttr2, 2, GL_FLOAT, GL_FALSE, 0, afTexCoord);
- glEnableVertexAttribArray(texCoordAttr2);
+ program2.setAttributeArray(texCoordAttr2, afTexCoord, 2);
GLfloat afNormals[] = {
@@ -278,50 +156,15 @@ void GLWidget::paintTexturedCube()
0,1,0, 0,1,0, 0,1,0,
0,1,0, 0,1,0, 0,1,0
};
- glVertexAttribPointer(normalAttr2, 3, GL_FLOAT, GL_FALSE, 0, afNormals);
- glEnableVertexAttribArray(normalAttr2);
+ program2.setAttributeArray(normalAttr2, afNormals, 3);
- glUniform1i(textureUniform2, 0); // use texture unit 0
+ program2.setUniformValue(textureUniform2, 0); // use texture unit 0
glDrawArrays(GL_TRIANGLES, 0, 36);
- glDisableVertexAttribArray(vertexAttr2);
- glDisableVertexAttribArray(normalAttr2);
- glDisableVertexAttribArray(texCoordAttr2);
-}
-
-static void reportCompileErrors(GLuint shader, const char *src)
-{
- GLint value = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
- bool compiled = (value != 0);
- value = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
- if (!compiled && value > 1) {
- char *log = new char [value];
- GLint len;
- glGetShaderInfoLog(shader, value, &len, log);
- qWarning("%s\n", log);
- qWarning("when compiling:\n%s\n", src);
- delete [] log;
- }
-}
-
-static void reportLinkErrors(GLuint program, const char *vsrc, const char *fsrc)
-{
- GLint value = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &value);
- bool linked = (value != 0);
- value = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
- if (!linked && value > 1) {
- char *log = new char [value];
- GLint len;
- glGetProgramInfoLog(program, value, &len, log);
- qWarning("%s\n", log);
- qWarning("when linking:\n%s\nwith:\n%s\n", vsrc, fsrc);
- delete [] log;
- }
+ program2.disableAttributeArray(vertexAttr2);
+ program2.disableAttributeArray(normalAttr2);
+ program2.disableAttributeArray(texCoordAttr2);
}
void GLWidget::initializeGL ()
@@ -332,8 +175,8 @@ void GLWidget::initializeGL ()
glGenTextures(1, &m_uiTexture);
m_uiTexture = bindTexture(QImage(":/qt.png"));
- GLuint vshader1 = glCreateShader(GL_VERTEX_SHADER);
- const char *vsrc1[1] = {
+ QGLShader *vshader1 = new QGLShader(QGLShader::VertexShader, this);
+ const char *vsrc1 =
"attribute highp vec4 vertex;\n"
"attribute mediump vec3 normal;\n"
"uniform mediump mat4 matrix;\n"
@@ -346,36 +189,28 @@ void GLWidget::initializeGL ()
" color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n"
" color = clamp(color, 0.0, 1.0);\n"
" gl_Position = matrix * vertex;\n"
- "}\n"
- };
- glShaderSource(vshader1, 1, vsrc1, 0);
- glCompileShader(vshader1);
- reportCompileErrors(vshader1, vsrc1[0]);
+ "}\n";
+ vshader1->setSourceCode(vsrc1);
- GLuint fshader1 = glCreateShader(GL_FRAGMENT_SHADER);
- const char *fsrc1[1] = {
+ QGLShader *fshader1 = new QGLShader(QGLShader::FragmentShader, this);
+ const char *fsrc1 =
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = color;\n"
- "}\n"
- };
- glShaderSource(fshader1, 1, fsrc1, 0);
- glCompileShader(fshader1);
- reportCompileErrors(fshader1, fsrc1[0]);
-
- program1 = glCreateProgram();
- glAttachShader(program1, vshader1);
- glAttachShader(program1, fshader1);
- glLinkProgram(program1);
- reportLinkErrors(program1, vsrc1[0], fsrc1[0]);
-
- vertexAttr1 = glGetAttribLocation(program1, "vertex");
- normalAttr1 = glGetAttribLocation(program1, "normal");
- matrixUniform1 = glGetUniformLocation(program1, "matrix");
-
- GLuint vshader2 = glCreateShader(GL_VERTEX_SHADER);
- const char *vsrc2[1] = {
+ "}\n";
+ fshader1->setSourceCode(fsrc1);
+
+ program1.addShader(vshader1);
+ program1.addShader(fshader1);
+ program1.link();
+
+ vertexAttr1 = program1.attributeLocation("vertex");
+ normalAttr1 = program1.attributeLocation("normal");
+ matrixUniform1 = program1.uniformLocation("matrix");
+
+ QGLShader *vshader2 = new QGLShader(QGLShader::VertexShader);
+ const char *vsrc2 =
"attribute highp vec4 vertex;\n"
"attribute highp vec4 texCoord;\n"
"attribute mediump vec3 normal;\n"
@@ -388,14 +223,11 @@ void GLWidget::initializeGL ()
" angle = max(dot(normal, toLight), 0.0);\n"
" gl_Position = matrix * vertex;\n"
" texc = texCoord;\n"
- "}\n"
- };
- glShaderSource(vshader2, 1, vsrc2, 0);
- glCompileShader(vshader2);
- reportCompileErrors(vshader2, vsrc2[0]);
+ "}\n";
+ vshader2->setSourceCode(vsrc2);
- GLuint fshader2 = glCreateShader(GL_FRAGMENT_SHADER);
- const char *fsrc2[1] = {
+ QGLShader *fshader2 = new QGLShader(QGLShader::FragmentShader);
+ const char *fsrc2 =
"varying highp vec4 texc;\n"
"uniform sampler2D tex;\n"
"varying mediump float angle;\n"
@@ -404,23 +236,18 @@ void GLWidget::initializeGL ()
" highp vec3 color = texture2D(tex, texc.st).rgb;\n"
" color = color * 0.2 + color * 0.8 * angle;\n"
" gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n"
- "}\n"
- };
- glShaderSource(fshader2, 1, fsrc2, 0);
- glCompileShader(fshader2);
- reportCompileErrors(fshader2, fsrc2[0]);
-
- program2 = glCreateProgram();
- glAttachShader(program2, vshader2);
- glAttachShader(program2, fshader2);
- glLinkProgram(program2);
- reportLinkErrors(program2, vsrc2[0], fsrc2[0]);
-
- vertexAttr2 = glGetAttribLocation(program2, "vertex");
- normalAttr2 = glGetAttribLocation(program2, "normal");
- texCoordAttr2 = glGetAttribLocation(program2, "texCoord");
- matrixUniform2 = glGetUniformLocation(program2, "matrix");
- textureUniform2 = glGetUniformLocation(program2, "tex");
+ "}\n";
+ fshader2->setSourceCode(fsrc2);
+
+ program2.addShader(vshader2);
+ program2.addShader(fshader2);
+ program2.link();
+
+ vertexAttr2 = program2.attributeLocation("vertex");
+ normalAttr2 = program2.attributeLocation("normal");
+ texCoordAttr2 = program2.attributeLocation("texCoord");
+ matrixUniform2 = program2.uniformLocation("matrix");
+ textureUniform2 = program2.uniformLocation("tex");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -450,24 +277,23 @@ void GLWidget::paintGL()
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
- GLfloat modelview[16];
- IdentityMatrix(modelview);
- RotateMatrix(modelview, m_fAngle, 0.0, 1.0, 0.0);
- RotateMatrix(modelview, m_fAngle, 1.0, 0.0, 0.0);
- RotateMatrix(modelview, m_fAngle, 0.0, 0.0, 1.0);
- ScaleMatrix(modelview, m_fScale, m_fScale, m_fScale);
- TranslateMatrix(modelview, 0, -0.2, 0);
+ QMatrix4x4 modelview;
+ modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
+ modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
+ modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f);
+ modelview.scale(m_fScale);
+ modelview.translate(0.0f, -0.2f, 0.0f);
if (qtLogo) {
- glUseProgram(program1);
- glUniformMatrix4fv(matrixUniform1, 1, GL_FALSE, modelview);
+ program1.enable();
+ program1.setUniformValue(matrixUniform1, modelview);
paintQtLogo();
- glUseProgram(0);
+ program1.disable();
} else {
- glUseProgram(program2);
- glUniformMatrix4fv(matrixUniform2, 1, GL_FALSE, modelview);
+ program2.enable();
+ program1.setUniformValue(matrixUniform2, modelview);
paintTexturedCube();
- glUseProgram(0);
+ program2.disable();
}
glDisable(GL_DEPTH_TEST);
@@ -563,80 +389,69 @@ void GLWidget::createGeometry()
extrude(x8, y8, x5, y5);
}
- m_vertexNumber = vertices.size();
- createdVertices = new GLfloat[m_vertexNumber];
- createdNormals = new GLfloat[m_vertexNumber];
- for (int i = 0;i < m_vertexNumber;i++) {
- createdVertices[i] = vertices.at(i) * 2;
- createdNormals[i] = normals.at(i);
- }
- vertices.clear();
- normals.clear();
+ for (int i = 0;i < vertices.size();i++)
+ vertices[i] *= 2.0f;
}
void GLWidget::quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4)
{
- qreal nx, ny, nz;
+ vertices << QVector3D(x1, y1, -0.05f);
+ vertices << QVector3D(x2, y2, -0.05f);
+ vertices << QVector3D(x4, y4, -0.05f);
- vertices << x1 << y1 << -0.05f;
- vertices << x2 << y2 << -0.05f;
- vertices << x4 << y4 << -0.05f;
+ vertices << QVector3D(x3, y3, -0.05f);
+ vertices << QVector3D(x4, y4, -0.05f);
+ vertices << QVector3D(x2, y2, -0.05f);
- vertices << x3 << y3 << -0.05f;
- vertices << x4 << y4 << -0.05f;
- vertices << x2 << y2 << -0.05f;
+ QVector3D n = QVector3D::normal
+ (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(x4 - x1, y4 - y1, 0.0f));
- CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0, x4 - x1, y4 - y1, 0);
- Normalize(nx, ny, nz);
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ vertices << QVector3D(x4, y4, 0.05f);
+ vertices << QVector3D(x2, y2, 0.05f);
+ vertices << QVector3D(x1, y1, 0.05f);
- vertices << x4 << y4 << 0.05f;
- vertices << x2 << y2 << 0.05f;
- vertices << x1 << y1 << 0.05f;
+ vertices << QVector3D(x2, y2, 0.05f);
+ vertices << QVector3D(x4, y4, 0.05f);
+ vertices << QVector3D(x3, y3, 0.05f);
- vertices << x2 << y2 << 0.05f;
- vertices << x4 << y4 << 0.05f;
- vertices << x3 << y3 << 0.05f;
+ n = QVector3D::normal
+ (QVector3D(x2 - x4, y2 - y4, 0.0f), QVector3D(x1 - x4, y1 - y4, 0.0f));
- CrossProduct(nx, ny, nz, x2 - x4, y2 - y4, 0, x1 - x4, y1 - y4, 0);
- Normalize(nx, ny, nz);
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
-
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
}
void GLWidget::extrude(qreal x1, qreal y1, qreal x2, qreal y2)
{
- qreal nx, ny, nz;
-
- vertices << x1 << y1 << +0.05f;
- vertices << x2 << y2 << +0.05f;
- vertices << x1 << y1 << -0.05f;
+ vertices << QVector3D(x1, y1, +0.05f);
+ vertices << QVector3D(x2, y2, +0.05f);
+ vertices << QVector3D(x1, y1, -0.05f);
- vertices << x2 << y2 << -0.05f;
- vertices << x1 << y1 << -0.05f;
- vertices << x2 << y2 << +0.05f;
+ vertices << QVector3D(x2, y2, -0.05f);
+ vertices << QVector3D(x1, y1, -0.05f);
+ vertices << QVector3D(x2, y2, +0.05f);
- CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0.0f, 0.0f, 0.0f, -0.1f);
- Normalize(nx, ny, nz);
+ QVector3D n = QVector3D::normal
+ (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f));
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
}
diff --git a/examples/opengl/hellogl_es2/glwidget.h b/examples/opengl/hellogl_es2/glwidget.h
index 9a7823a..596e1cc 100644
--- a/examples/opengl/hellogl_es2/glwidget.h
+++ b/examples/opengl/hellogl_es2/glwidget.h
@@ -43,7 +43,11 @@
#define GLWIDGET_H
#include <QGLWidget>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtOpenGL/qglshaderprogram.h>
#include <QTime>
+#include <QVector>
class Bubble;
class GLWidget : public QGLWidget {
@@ -71,24 +75,21 @@ private:
void createBubbles(int number);
void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4);
void extrude(qreal x1, qreal y1, qreal x2, qreal y2);
- QList<qreal> vertices;
- QList<qreal> normals;
- GLfloat *createdVertices;
- GLfloat *createdNormals;
- int m_vertexNumber;
+ QVector<QVector3D> vertices;
+ QVector<QVector3D> normals;
bool qtLogo;
QList<Bubble*> bubbles;
int frames;
QTime time;
- GLuint program1;
- GLuint program2;
- GLuint vertexAttr1;
- GLuint normalAttr1;
- GLuint matrixUniform1;
- GLuint vertexAttr2;
- GLuint normalAttr2;
- GLuint texCoordAttr2;
- GLuint matrixUniform2;
- GLuint textureUniform2;
+ QGLShaderProgram program1;
+ QGLShaderProgram program2;
+ int vertexAttr1;
+ int normalAttr1;
+ int matrixUniform1;
+ int vertexAttr2;
+ int normalAttr2;
+ int texCoordAttr2;
+ int matrixUniform2;
+ int textureUniform2;
};
#endif
diff --git a/src/opengl/gl2paintengineex/qglshader_p.h b/src/opengl/gl2paintengineex/qglshader_p.h
index 1625b84..64c9a42 100644
--- a/src/opengl/gl2paintengineex/qglshader_p.h
+++ b/src/opengl/gl2paintengineex/qglshader_p.h
@@ -81,6 +81,8 @@ SAMPLER_2D_SHADOW.
#include <QtOpenGL>
+#define QGLShader QGLEngineShader
+#define QGLShaderProgram QGLEngineShaderProgram
typedef struct {
GLfloat a;
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 78aaddb..cdf31cc 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -25,12 +25,14 @@ HEADERS += qgl.h \
qglcolormap.h \
qglpixelbuffer.h \
qglframebufferobject.h \
+ qglshaderprogram.h
SOURCES += qgl.cpp \
qglcolormap.cpp \
qglpixelbuffer.cpp \
qglframebufferobject.cpp \
qglextensions.cpp \
+ qglshaderprogram.cpp
!contains(QT_CONFIG, opengles2) {
HEADERS += qpaintengine_opengl_p.h qglpixmapfilter_p.h
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 8357cf9..5ba669b 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -150,36 +150,158 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx)
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
+#if defined(QT_OPENGL_ES_2)
+ // The GLSL shader functions are always present in OpenGL/ES 2.0.
+ // The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
+ if (!QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved) {
+ glGetProgramBinaryOES = (_glGetProgramBinaryOES) ctx->getProcAddress(QLatin1String("glGetProgramBinaryOES"));
+ glProgramBinaryOES = (_glProgramBinaryOES) ctx->getProcAddress(QLatin1String("glProgramBinaryOES"));
+ QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved = true;
+ }
+ return true;
+#else
if (glCreateShader)
return true;
glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
- glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
- glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
- glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
-
- glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
- glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
- glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
- glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
- glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
- glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
-
- glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
- glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
- glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
-
- glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
- glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
- glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
- glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
- glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
- glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
-
- return glCreateShader && glShaderSource && glCompileShader && glDeleteProgram &&
- glCreateProgram && glAttachShader && glDetachShader && glLinkProgram && glUseProgram &&
- glDeleteProgram && glGetShaderInfoLog && glGetShaderiv && glGetProgramiv && glGetUniformLocation &&
- glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv;
+ if (glCreateShader) {
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinary"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
+ glIsShader = (_glIsShader) ctx->getProcAddress(QLatin1String("glIsShader"));
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
+ glIsProgram = (_glIsProgram) ctx->getProcAddress(QLatin1String("glIsProgram"));
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSource"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1iv"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fv"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fv"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fv"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fv"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fv"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fv"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocation"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fv"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fv"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fv"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fv"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
+ } else {
+ // We may not have the standard shader functions, but we might
+ // have the older ARB functions instead.
+ glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShaderObjectARB"));
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSourceARB"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinaryARB"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShaderARB"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsShader = 0;
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgramObjectARB"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachObjectARB"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachObjectARB"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgramARB"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgramObjectARB"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsProgram = 0;
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSourceARB"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocationARB"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fvARB"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fvARB"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fvARB"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fvARB"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1iARB"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1ivARB"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fvARB"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fvARB"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fvARB"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fvARB"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fvARB"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fvARB"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fvARB"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fvARB"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fvARB"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocationARB"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocationARB"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fvARB"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fvARB"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fvARB"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fvARB"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointerARB"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB"));
+ }
+
+ // Note: glShaderBinary(), glIsShader(), glIsProgram(), and
+ // glUniformMatrixNxMfv() are optional, but all other functions
+ // are required.
+
+ return glCreateShader &&
+ glShaderSource &&
+ glCompileShader &&
+ glDeleteProgram &&
+ glCreateProgram &&
+ glAttachShader &&
+ glDetachShader &&
+ glLinkProgram &&
+ glUseProgram &&
+ glDeleteProgram &&
+ glGetShaderInfoLog &&
+ glGetShaderiv &&
+ glGetShaderSource &&
+ glGetProgramiv &&
+ glGetProgramInfoLog &&
+ glGetUniformLocation &&
+ glUniform1fv &&
+ glUniform2fv &&
+ glUniform3fv &&
+ glUniform4fv &&
+ glUniform1i &&
+ glUniform1iv &&
+ glUniformMatrix2fv &&
+ glUniformMatrix3fv &&
+ glUniformMatrix4fv &&
+ glBindAttribLocation &&
+ glGetAttribLocation &&
+ glVertexAttrib1fv &&
+ glVertexAttrib2fv &&
+ glVertexAttrib3fv &&
+ glVertexAttrib4fv &&
+ glVertexAttribPointer &&
+ glDisableVertexAttribArray &&
+ glEnableVertexAttribArray;
+#endif
}
QT_END_NAMESPACE
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index a0517f5..f71ae9d 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -92,8 +92,10 @@ typedef void (APIENTRY *_glProgramLocalParameter4fvARB) (GLenum, GLuint, const G
// GLSL
typedef GLuint (APIENTRY *_glCreateShader) (GLenum);
typedef void (APIENTRY *_glShaderSource) (GLuint, GLsizei, const char **, const GLint *);
+typedef void (APIENTRY *_glShaderBinary) (GLint, const GLuint*, GLenum, const void*, GLint);
typedef void (APIENTRY *_glCompileShader) (GLuint);
typedef void (APIENTRY *_glDeleteShader) (GLuint);
+typedef GLboolean (APIENTRY *_glIsShader) (GLuint);
typedef GLuint (APIENTRY *_glCreateProgram) ();
typedef void (APIENTRY *_glAttachShader) (GLuint, GLuint);
@@ -101,17 +103,43 @@ typedef void (APIENTRY *_glDetachShader) (GLuint, GLuint);
typedef void (APIENTRY *_glLinkProgram) (GLuint);
typedef void (APIENTRY *_glUseProgram) (GLuint);
typedef void (APIENTRY *_glDeleteProgram) (GLuint);
+typedef GLboolean (APIENTRY *_glIsProgram) (GLuint);
typedef void (APIENTRY *_glGetShaderInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetShaderiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetShaderSource) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetProgramiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetProgramInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
+typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
+typedef void (APIENTRY *_glUniform1iv) (GLint, GLsizei, const GLint *);
+typedef void (APIENTRY *_glUniformMatrix2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+
+typedef void (APIENTRY *_glBindAttribLocation) (GLuint, GLuint, const char *);
+typedef GLint (APIENTRY *_glGetAttribLocation) (GLuint, const char *);
+typedef void (APIENTRY *_glVertexAttrib1fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib2fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib3fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib4fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttribPointer) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+typedef void (APIENTRY *_glDisableVertexAttribArray) (GLuint);
+typedef void (APIENTRY *_glEnableVertexAttribArray) (GLuint);
+
+typedef void (APIENTRY *_glGetProgramBinaryOES) (GLuint, GLsizei, GLsizei *, GLenum *, void *);
+typedef void (APIENTRY *_glProgramBinaryOES) (GLuint, GLenum, const void *, GLint);
typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
@@ -153,10 +181,13 @@ struct QGLExtensionFuncs
qt_glGenProgramsARB = 0;
qt_glProgramLocalParameter4fvARB = 0;
+#if !defined(QT_OPENGL_ES_2)
qt_glCreateShader = 0;
qt_glShaderSource = 0;
+ qt_glShaderBinary = 0;
qt_glCompileShader = 0;
qt_glDeleteShader = 0;
+ qt_glIsShader = 0;
qt_glCreateProgram = 0;
qt_glAttachShader = 0;
@@ -164,10 +195,13 @@ struct QGLExtensionFuncs
qt_glLinkProgram = 0;
qt_glUseProgram = 0;
qt_glDeleteProgram = 0;
+ qt_glIsProgram = 0;
qt_glGetShaderInfoLog = 0;
qt_glGetShaderiv = 0;
+ qt_glGetShaderSource = 0;
qt_glGetProgramiv = 0;
+ qt_glGetProgramInfoLog = 0;
qt_glGetUniformLocation = 0;
qt_glUniform4fv = 0;
@@ -175,6 +209,32 @@ struct QGLExtensionFuncs
qt_glUniform2fv = 0;
qt_glUniform1fv = 0;
qt_glUniform1i = 0;
+ qt_glUniform1iv = 0;
+ qt_glUniformMatrix2fv = 0;
+ qt_glUniformMatrix3fv = 0;
+ qt_glUniformMatrix4fv = 0;
+ qt_glUniformMatrix2x3fv = 0;
+ qt_glUniformMatrix2x4fv = 0;
+ qt_glUniformMatrix3x2fv = 0;
+ qt_glUniformMatrix3x4fv = 0;
+ qt_glUniformMatrix4x2fv = 0;
+ qt_glUniformMatrix4x3fv = 0;
+
+ qt_glBindAttribLocation = 0;
+ qt_glGetAttribLocation = 0;
+ qt_glVertexAttrib1fv = 0;
+ qt_glVertexAttrib2fv = 0;
+ qt_glVertexAttrib3fv = 0;
+ qt_glVertexAttrib4fv = 0;
+ qt_glVertexAttribPointer = 0;
+ qt_glDisableVertexAttribArray = 0;
+ qt_glEnableVertexAttribArray = 0;
+#else
+ qt_glslResolved = false;
+
+ qt_glGetProgramBinaryOES = 0;
+ qt_glProgramBinaryOES = 0;
+#endif
qt_glActiveStencilFaceEXT = 0;
@@ -215,11 +275,14 @@ struct QGLExtensionFuncs
_glGenProgramsARB qt_glGenProgramsARB;
_glProgramLocalParameter4fvARB qt_glProgramLocalParameter4fvARB;
+#if !defined(QT_OPENGL_ES_2)
// GLSL definitions
_glCreateShader qt_glCreateShader;
_glShaderSource qt_glShaderSource;
+ _glShaderBinary qt_glShaderBinary;
_glCompileShader qt_glCompileShader;
_glDeleteShader qt_glDeleteShader;
+ _glIsShader qt_glIsShader;
_glCreateProgram qt_glCreateProgram;
_glAttachShader qt_glAttachShader;
@@ -227,10 +290,13 @@ struct QGLExtensionFuncs
_glLinkProgram qt_glLinkProgram;
_glUseProgram qt_glUseProgram;
_glDeleteProgram qt_glDeleteProgram;
+ _glIsProgram qt_glIsProgram;
_glGetShaderInfoLog qt_glGetShaderInfoLog;
_glGetShaderiv qt_glGetShaderiv;
+ _glGetShaderSource qt_glGetShaderSource;
_glGetProgramiv qt_glGetProgramiv;
+ _glGetProgramInfoLog qt_glGetProgramInfoLog;
_glGetUniformLocation qt_glGetUniformLocation;
_glUniform4fv qt_glUniform4fv;
@@ -238,6 +304,32 @@ struct QGLExtensionFuncs
_glUniform2fv qt_glUniform2fv;
_glUniform1fv qt_glUniform1fv;
_glUniform1i qt_glUniform1i;
+ _glUniform1iv qt_glUniform1iv;
+ _glUniformMatrix2fv qt_glUniformMatrix2fv;
+ _glUniformMatrix3fv qt_glUniformMatrix3fv;
+ _glUniformMatrix4fv qt_glUniformMatrix4fv;
+ _glUniformMatrix2x3fv qt_glUniformMatrix2x3fv;
+ _glUniformMatrix2x4fv qt_glUniformMatrix2x4fv;
+ _glUniformMatrix3x2fv qt_glUniformMatrix3x2fv;
+ _glUniformMatrix3x4fv qt_glUniformMatrix3x4fv;
+ _glUniformMatrix4x2fv qt_glUniformMatrix4x2fv;
+ _glUniformMatrix4x3fv qt_glUniformMatrix4x3fv;
+
+ _glBindAttribLocation qt_glBindAttribLocation;
+ _glGetAttribLocation qt_glGetAttribLocation;
+ _glVertexAttrib1fv qt_glVertexAttrib1fv;
+ _glVertexAttrib2fv qt_glVertexAttrib2fv;
+ _glVertexAttrib3fv qt_glVertexAttrib3fv;
+ _glVertexAttrib4fv qt_glVertexAttrib4fv;
+ _glVertexAttribPointer qt_glVertexAttribPointer;
+ _glDisableVertexAttribArray qt_glDisableVertexAttribArray;
+ _glEnableVertexAttribArray qt_glEnableVertexAttribArray;
+#else
+ bool qt_glslResolved;
+
+ _glGetProgramBinaryOES qt_glGetProgramBinaryOES;
+ _glProgramBinaryOES qt_glProgramBinaryOES;
+#endif
_glActiveStencilFaceEXT qt_glActiveStencilFaceEXT;
@@ -479,10 +571,14 @@ struct QGLExtensionFuncs
#define glMapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glMapBufferARB
#define glUnmapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUnmapBufferARB
+#if !defined(QT_OPENGL_ES_2)
+
#define glCreateShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateShader
#define glShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderSource
+#define glShaderBinary QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderBinary
#define glCompileShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCompileShader
#define glDeleteShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteShader
+#define glIsShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsShader
#define glCreateProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateProgram
#define glAttachShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glAttachShader
@@ -490,10 +586,13 @@ struct QGLExtensionFuncs
#define glLinkProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glLinkProgram
#define glUseProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUseProgram
#define glDeleteProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgram
+#define glIsProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsProgram
#define glGetShaderInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderInfoLog
#define glGetShaderiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderiv
+#define glGetShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderSource
#define glGetProgramiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramiv
+#define glGetProgramInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramInfoLog
#define glGetUniformLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetUniformLocation
#define glUniform4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform4fv
@@ -501,6 +600,33 @@ struct QGLExtensionFuncs
#define glUniform2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform2fv
#define glUniform1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1fv
#define glUniform1i QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1i
+#define glUniform1iv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1iv
+#define glUniformMatrix2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2fv
+#define glUniformMatrix3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3fv
+#define glUniformMatrix4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4fv
+#define glUniformMatrix2x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x3fv
+#define glUniformMatrix2x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x4fv
+#define glUniformMatrix3x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x2fv
+#define glUniformMatrix3x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x4fv
+#define glUniformMatrix4x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x2fv
+#define glUniformMatrix4x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x3fv
+
+#define glBindAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindAttribLocation
+#define glGetAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetAttribLocation
+#define glVertexAttrib1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib1fv
+#define glVertexAttrib2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib2fv
+#define glVertexAttrib3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib3fv
+#define glVertexAttrib4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib4fv
+#define glVertexAttribPointer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttribPointer
+#define glDisableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDisableVertexAttribArray
+#define glEnableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glEnableVertexAttribArray
+
+#else // QT_OPENGL_ES_2
+
+#define glGetProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramBinaryOES
+#define glProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramBinaryOES
+
+#endif // QT_OPENGL_ES_2
extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
bool qt_resolve_buffer_extensions(QGLContext *ctx);
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index ff23948..4b811e5 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -45,27 +45,12 @@
#include "qpaintengine_opengl_p.h"
#include "qglpixelbuffer.h"
-#include "qglextensions_p.h"
+#include "qglshaderprogram.h"
#include "qgl_p.h"
#include "private/qapplication_p.h"
-#ifndef GL_FRAGMENT_SHADER
-#define GL_FRAGMENT_SHADER 0x8B30
-#endif
-
-#ifndef GL_COMPILE_STATUS
-#define GL_COMPILE_STATUS 0x8B81
-#endif
-
-#ifndef GL_LINK_STATUS
-#define GL_LINK_STATUS 0x8B82
-#endif
-
-
-
-
QT_BEGIN_NAMESPACE
@@ -79,117 +64,6 @@ void QGLPixmapFilterBase::drawImpl(QPainter *painter, const QPointF &pos, const
processGL(painter, pos, src, source);
}
-QGLSLProgram::QGLSLProgram(const QString &src)
- : ctx(QGLContext::currentContext())
-{
- if (!qt_resolve_glsl_extensions(const_cast<QGLContext *>(ctx))) {
- qWarning("Failed to resolve GLSL functions");
- m_valid = false;
- return;
- }
-
- m_shader = glCreateShader(GL_FRAGMENT_SHADER);
-
- const QByteArray src_ba = src.toAscii();
- const char *src_cstr = src_ba.constData();
-
- glShaderSource(m_shader, 1, &src_cstr, 0);
- glCompileShader(m_shader);
- glGetShaderiv(m_shader, GL_COMPILE_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to compile GLSL shader:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-
- m_program = glCreateProgram();
- glAttachShader(m_program, m_shader);
- glLinkProgram(m_program);
- glGetProgramiv(m_program, GL_LINK_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to link GLSL program:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-}
-
-QGLSLProgram::~QGLSLProgram()
-{
- glDeleteProgram(m_program);
- glDeleteShader(m_shader);
-}
-
-bool QGLSLProgram::success() const
-{
- return m_valid;
-}
-
-void QGLSLProgram::enable()
-{
- glUseProgram(m_program);
-}
-
-void QGLSLProgram::disable()
-{
- glUseProgram(0);
-}
-
-typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
-
-int QGLSLProgram::getUniformLocation(const QString &name)
-{
- return glGetUniformLocation(m_program, name.toAscii().constData());
-}
-
-void QGLSLProgram::setUniform(int uniform, int value)
-{
- enable();
- glUniform1i(uniform, value);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal value)
-{
- enable();
- GLfloat v[] = { value };
- glUniform1fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2)
-{
- enable();
- GLfloat v[] = { v1, v2 };
- glUniform2fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3)
-{
- enable();
- GLfloat v[] = { v1, v2, v3 };
- glUniform3fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4)
-{
- enable();
- GLfloat v[] = { v1, v2, v3, v4 };
- glUniform4fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, int count, float *v)
-{
- enable();
- glUniform1fv(uniform, count, v);
-}
-
class QGLPixmapColorizeFilter: public QGLPixmapFilter<QPixmapColorizeFilter>
{
public:
@@ -199,8 +73,8 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &pixmap, const QRectF &srcRect) const;
private:
- mutable QGLSLProgram m_program;
- uint m_colorUniform;
+ mutable QGLShaderProgram m_program;
+ int m_colorUniform;
};
class QGLPixmapConvolutionFilter: public QGLPixmapFilter<QPixmapConvolutionFilter>
@@ -213,11 +87,11 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const;
private:
- QString generateConvolutionShader() const;
+ QByteArray generateConvolutionShader() const;
- mutable QGLSLProgram *m_program;
- mutable uint m_scaleUniform;
- mutable uint m_matrixUniform;
+ mutable QGLShaderProgram *m_program;
+ mutable int m_scaleUniform;
+ mutable int m_matrixUniform;
mutable int m_kernelWidth;
mutable int m_kernelHeight;
@@ -294,10 +168,12 @@ static const char *qt_gl_colorize_filter =
"}";
QGLPixmapColorizeFilter::QGLPixmapColorizeFilter()
- : m_program(QLatin1String(qt_gl_colorize_filter))
{
- m_program.setUniform(m_program.getUniformLocation(QLatin1String("texture")), 0); // GL_TEXTURE_0
- m_colorUniform = m_program.getUniformLocation(QLatin1String("color"));
+ m_program.addShader(QGLShader::FragmentShader, qt_gl_colorize_filter);
+ m_program.link();
+ m_program.enable();
+ m_program.setUniformValue(m_program.uniformLocation("texture"), 0); // GL_TEXTURE_0
+ m_colorUniform = m_program.uniformLocation("color");
}
bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
@@ -305,10 +181,10 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
bindTexture(src);
QColor col = color();
- m_program.setUniform(m_colorUniform, col.redF(), col.greenF(), col.blueF());
+ m_program.enable();
+ m_program.setUniformValue(m_colorUniform, col.redF(), col.greenF(), col.blueF());
QRectF target = (srcRect.isNull() ? QRectF(src.rect()) : srcRect).translated(pos);
- m_program.enable();
qgl_drawTexture(target, src.width(), src.height(), srcRect);
m_program.disable();
@@ -316,7 +192,7 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
}
// generates convolution filter code for arbitrary sized kernel
-QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
+QByteArray QGLPixmapConvolutionFilter::generateConvolutionShader() const {
QByteArray code;
code.append("uniform sampler2D texture;\n");
code.append("uniform vec2 inv_texture_size;\n");
@@ -352,7 +228,7 @@ QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
code.append(" }\n");
code.append(" gl_FragColor = sum;\n");
code.append("}");
- return QLatin1String(code);
+ return code;
}
QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter()
@@ -384,10 +260,12 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
m_kernelWidth = columns();
m_kernelHeight = rows();
- QString code = generateConvolutionShader();
- m_program = new QGLSLProgram(code);
- m_scaleUniform = m_program->getUniformLocation(QLatin1String("inv_texture_size"));
- m_matrixUniform = m_program->getUniformLocation(QLatin1String("matrix"));
+ QByteArray code = generateConvolutionShader();
+ m_program = new QGLShaderProgram();
+ m_program->addShader(QGLShader::FragmentShader, code);
+ m_program->link();
+ m_scaleUniform = m_program->uniformLocation("inv_texture_size");
+ m_matrixUniform = m_program->uniformLocation("matrix");
}
const qreal *kernel = convolutionKernel();
@@ -397,10 +275,10 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
const qreal iw = 1.0 / src.width();
const qreal ih = 1.0 / src.height();
- m_program->setUniform(m_scaleUniform, iw, ih);
- m_program->setUniform(m_matrixUniform, m_kernelWidth * m_kernelHeight, conv);
-
m_program->enable();
+ m_program->setUniformValue(m_scaleUniform, iw, ih);
+ m_program->setUniformValueArray(m_matrixUniform, conv, m_kernelWidth * m_kernelHeight, 1);
+
qgl_drawTexture(target, src.width(), src.height(), boundingRectFor(srcRect));
m_program->disable();
return true;
diff --git a/src/opengl/qglpixmapfilter_p.h b/src/opengl/qglpixmapfilter_p.h
index dc2eea6..d6742fc 100644
--- a/src/opengl/qglpixmapfilter_p.h
+++ b/src/opengl/qglpixmapfilter_p.h
@@ -87,35 +87,6 @@ public:
}
};
-class Q_OPENGL_EXPORT QGLSLProgram
-{
-public:
- QGLSLProgram(const QString &src);
- ~QGLSLProgram();
-
- bool success() const;
-
- void enable();
- void disable();
-
- int getUniformLocation(const QString &name);
-
- void setUniform(int uniform, int value);
- void setUniform(int uniform, qreal value);
- void setUniform(int uniform, qreal v1, qreal v2);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4);
- void setUniform(int uniform, int count, float *v);
-
-private:
- GLuint m_shader;
- GLuint m_program;
-
- GLint m_valid;
-
- const QGLContext *ctx;
-};
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
new file mode 100644
index 0000000..5738acd
--- /dev/null
+++ b/src/opengl/qglshaderprogram.cpp
@@ -0,0 +1,2828 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglshaderprogram.h"
+#include "qglextensions_p.h"
+#include "qgl_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_OPENGL_ES_1_CL)
+
+/*!
+ \class QGLShaderProgram
+ \brief The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
+ \since 4.6
+
+ \section1 Introduction
+
+ This class supports shader programs written in the OpenGL Shading
+ Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ The following example creates a vertex shader program using the
+ supplied source \c{code}. Once compiled and linked, the shader
+ program is activated in the current QGLContext by calling
+ QGLShaderProgram::enable():
+
+ \code
+ QGLShader shader(QGLShader::VertexShader);
+ shader.setSourceCode(code);
+
+ QGLShaderProgram program(context);
+ program.addShader(shader);
+ program.link();
+
+ program.enable();
+ \endcode
+
+ \section1 Writing portable shaders
+
+ Shader programs can be difficult to reuse across OpenGL implementations
+ because of varying levels of support for standard vertex attributes and
+ uniform variables. In particular, GLSL/ES lacks all of the
+ standard variables that are present on desktop OpenGL systems:
+ \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL
+ lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}.
+
+ The QGLShaderProgram class makes the process of writing portable shaders
+ easier by prefixing all shader programs with the following lines on
+ desktop OpenGL:
+
+ \code
+ #define highp
+ #define mediump
+ #define lowp
+ \endcode
+
+ This makes it possible to run most GLSL/ES shader programs
+ on desktop systems. The programmer should restrict themselves
+ to just features that are present in GLSL/ES, and avoid
+ standard variable names that only work on the desktop.
+
+ \section1 Simple shader example
+
+ \code
+ program.addShader(QGLShader::VertexShader,
+ "attribute highp vec4 vertex;\n"
+ "attribute mediump mat4 matrix;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = matrix * vertex;\n"
+ "}");
+ program.addShader(QGLShader::FragmentShader,
+ "uniform mediump vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}");
+ program.link();
+ program.enable();
+
+ int vertexLocation = program.attributeLocation("vertex");
+ int matrixLocation = program.attributeLocation("matrix");
+ int colorLocation = program.uniformLocation("color");
+ \endcode
+
+ With the above shader program active, we can draw a green triangle
+ as follows:
+
+ \code
+ static GLfloat const triangleVertices[] = {
+ 60.0f, 10.0f, 0.0f,
+ 110.0f, 110.0f, 0.0f,
+ 10.0f, 110.0f, 0.0f
+ };
+
+ QColor color(0, 255, 0, 255);
+
+ QMatrix4x4 pmvMatrix;
+ pmvMatrix.ortho(rect());
+
+ program.setAttributeArray(vertexLocation, triangleVertices, 3);
+ program.setUniformValue(matrixLocation, pmvMatrix);
+ program.setUniformValue(colorLocation, color);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ \endcode
+
+ \section1 Partial shaders
+
+ Desktop GLSL can attach an arbitrary number of vertex and fragment
+ shaders to a shader program. Embedded GLSL/ES on the other hand
+ supports only a single shader of each type on a shader program.
+
+ Multiple shaders of the same type can be useful when large libraries
+ of shaders are needed. Common functions can be factored out into
+ library shaders that can be reused in multiple shader programs.
+
+ To support this use of shaders, the application programmer can
+ create shaders with the QGLShader::PartialVertexShader and
+ QGLShader::PartialFragmentShader types. These types direct
+ QGLShader and QGLShaderProgram to delay shader compilation until
+ link time.
+
+ When link() is called, the sources for the partial shaders are
+ concatenated, and a single vertex or fragment shader is compiled
+ and linked into the shader program.
+
+ It is more efficient to use the QGLShader::VertexShader and
+ QGLShader::FragmentShader when there is only one shader of that
+ type in the program.
+
+ \sa QGLShader
+*/
+
+/*!
+ \class QGLShader
+ \brief The QGLShader class allows OpenGL shaders to be compiled.
+ \since 4.6
+
+ This class supports shaders written in the OpenGL Shading Language (GLSL)
+ and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ \sa QGLShaderProgram
+*/
+
+/*!
+ \enum QGLShader::ShaderType
+ This enum specifies the type of QGLShader that is being created.
+
+ \value VertexShader Vertex shader written in the OpenGL Shading Language (GLSL).
+ \value FragmentShader Fragment shader written in the OpenGL Shading Language (GLSL).
+ \value PartialVertexShader Partial vertex shader that will be concatenated with all other partial vertex shaders at link time.
+ \value PartialFragmentShader Partial fragment shader that will be concatenated with all other partial fragment shaders at link time.
+*/
+
+#ifndef GL_FRAGMENT_SHADER
+#define GL_FRAGMENT_SHADER 0x8B30
+#endif
+#ifndef GL_VERTEX_SHADER
+#define GL_VERTEX_SHADER 0x8B31
+#endif
+#ifndef GL_COMPILE_STATUS
+#define GL_COMPILE_STATUS 0x8B81
+#endif
+#ifndef GL_LINK_STATUS
+#define GL_LINK_STATUS 0x8B82
+#endif
+#ifndef GL_INFO_LOG_LENGTH
+#define GL_INFO_LOG_LENGTH 0x8B84
+#endif
+#ifndef GL_ACTIVE_UNIFORMS
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#endif
+#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTES
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#endif
+#ifndef GL_CURRENT_VERTEX_ATTRIB
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#endif
+#ifndef GL_SHADER_SOURCE_LENGTH
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#endif
+#ifndef GL_SHADER_BINARY_FORMATS
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#endif
+#ifndef GL_NUM_SHADER_BINARY_FORMATS
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#endif
+
+class QGLShaderPrivate
+{
+public:
+ QGLShaderPrivate(QGLShader::ShaderType type, const QGLContext *ctx)
+ {
+ context = ctx;
+ shader = 0;
+ shaderType = type;
+ compiled = false;
+ isPartial = (type == QGLShader::PartialVertexShader ||
+ type == QGLShader::PartialFragmentShader);
+ hasPartialSource = false;
+ }
+
+ const QGLContext *context;
+ GLuint shader;
+ QGLShader::ShaderType shaderType;
+ bool compiled;
+ bool isPartial;
+ bool hasPartialSource;
+ QString errors;
+ QByteArray partialSource;
+
+ bool create();
+ bool compile();
+};
+
+#define ctx context
+
+bool QGLShaderPrivate::create()
+{
+ if (isPartial)
+ return true;
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) {
+ if (shaderType == QGLShader::VertexShader)
+ shader = glCreateShader(GL_VERTEX_SHADER);
+ else
+ shader = glCreateShader(GL_FRAGMENT_SHADER);
+ if (!shader) {
+ qWarning() << "QGLShader: could not create shader";
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QGLShaderPrivate::compile()
+{
+ // Partial shaders are compiled during QGLShaderProgram::link().
+ if (isPartial && hasPartialSource) {
+ compiled = true;
+ return true;
+ }
+ if (!shader)
+ return false;
+ glCompileShader(shader);
+ GLint value = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
+ compiled = (value != 0);
+ value = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
+ if (!compiled && value > 1) {
+ char *log = new char [value];
+ GLint len;
+ glGetShaderInfoLog(shader, value, &len, log);
+ errors = QString::fromLatin1(log);
+ qWarning() << "QGLShader::compile:" << errors;
+ delete [] log;
+ }
+ return compiled;
+}
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ then isValid() will return false.
+
+ This constructor is normally followed by a call to setSourceCode()
+ or setSourceCodeFile().
+
+ The shader will be associated with the current QGLContext.
+
+ \sa setSourceCode(), setSourceCodeFile(), isValid()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader(const QString& fileName, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, QGLContext::currentContext());
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, QGLContext::currentContext());
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ then isValid() will return false.
+
+ This constructor is normally followed by a call to setSourceCode()
+ or setSourceCodeFile().
+
+ The shader will be associated with \a context.
+
+ \sa setSourceCode(), setSourceCodeFile(), isValid()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader(const QString& fileName, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, context);
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, context);
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Deletes this shader. If the shader has been attached to a
+ QGLShaderProgram object, then the actual shader will stay around
+ until the QGLShaderProgram is destroyed.
+*/
+QGLShader::~QGLShader()
+{
+ if (d->shader)
+ glDeleteShader(d->shader);
+ delete d;
+}
+
+/*!
+ Returns true if this shader is valid. Shaders become invalid
+ when they are destroyed and no longer attached to a QGLShaderProgram.
+*/
+bool QGLShader::isValid() const
+{
+ if (d->isPartial && d->hasPartialSource)
+ return true;
+ if (!d->shader)
+ return false;
+#if defined(QT_OPENGL_ES_2)
+ return glIsShader(d->shader);
+#else
+ // glIsShader() may not exist on some systems.
+ return (!glIsShader || glIsShader(d->shader));
+#endif
+}
+
+/*!
+ Returns the type of this shader.
+*/
+QGLShader::ShaderType QGLShader::shaderType() const
+{
+ return d->shaderType;
+}
+
+// The precision qualifiers are useful on OpenGL/ES systems,
+// but usually not present on desktop systems. Define the
+// keywords to empty strings on desktop systems.
+#ifndef QT_OPENGL_ES
+#define QGL_DEFINE_QUALIFIERS 1
+static const char qualifierDefines[] =
+ "#define lowp\n"
+ "#define mediump\n"
+ "#define highp\n";
+#endif
+
+/*!
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const char *source)
+{
+ if (d->isPartial) {
+ d->partialSource = QByteArray(source);
+ d->hasPartialSource = true;
+ return d->compile();
+ } else if (d->shader) {
+ QVarLengthArray<const char *> src;
+#ifdef QGL_DEFINE_QUALIFIERS
+ src.append(qualifierDefines);
+#endif
+ src.append(source);
+ glShaderSource(d->shader, src.size(), src.data(), 0);
+ return d->compile();
+ } else {
+ return false;
+ }
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const QByteArray& source)
+{
+ return setSourceCode(source.constData());
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const QString& source)
+{
+ return setSourceCode(source.toLatin1().constData());
+}
+
+/*!
+ Sets the source code for this shader to the contents of \a fileName
+ and compiles it. Returns true if the file could be opened and the
+ source compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCodeFile(const QString& fileName)
+{
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly)) {
+ qWarning() << "QGLShader: Unable to open file" << fileName;
+ return false;
+ }
+
+ QByteArray contents = file.readAll();
+ return setSourceCode(contents.constData());
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setBinaryCode(GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ glShaderBinary(1, &(d->shader), format, binary, length);
+ return (glGetError() == GL_NO_ERROR);
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ The \a otherShader will also have binary code set on it. This is
+ for the case where \a binary contains both vertex and fragment
+ shader code.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setBinaryCode
+ (QGLShader& otherShader, GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ if (otherShader.d->isPartial || !otherShader.d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ GLuint shaders[2];
+ shaders[0] = d->shader;
+ shaders[1] = otherShader.d->shader;
+ glShaderBinary(2, shaders, format, binary, length);
+ return (glGetError() == GL_NO_ERROR);
+}
+
+/*!
+ Returns a list of all binary formats that are supported by
+ setBinaryCode() on this system.
+
+ \sa setBinaryCode()
+*/
+QList<GLenum> QGLShader::shaderBinaryFormats()
+{
+ GLint num;
+ QList<GLenum> list;
+ glGetError(); // Clear error state.
+ glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &num);
+ if (glGetError() != GL_NO_ERROR || num <= 0)
+ return list;
+ QVarLengthArray<GLint> formats(num);
+ glGetIntegerv(GL_SHADER_BINARY_FORMATS, formats.data());
+ for (GLint i = 0; i < num; ++i)
+ list += (GLenum)(formats[i]);
+ return list;
+}
+
+/*!
+ Returns the source code for this shader.
+
+ \sa setSourceCode()
+*/
+QByteArray QGLShader::sourceCode() const
+{
+ if (d->isPartial)
+ return d->partialSource;
+ if (!d->shader)
+ return QByteArray();
+ GLint size = 0;
+ glGetShaderiv(d->shader, GL_SHADER_SOURCE_LENGTH, &size);
+ if (size <= 0)
+ return QByteArray();
+ GLint len = 0;
+ char *source = new char [size];
+ glGetShaderSource(d->shader, size, &len, source);
+ QByteArray src(source);
+ delete [] source;
+ return src;
+}
+
+/*!
+ Returns true if this shader has been compiled; false otherwise.
+
+ \sa setSourceCode()
+*/
+bool QGLShader::isCompiled() const
+{
+ return d->compiled;
+}
+
+/*!
+ Returns the errors that occurred during the last compile.
+
+ \sa setSourceCode()
+*/
+QString QGLShader::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ this function will always return zero. Partial shaders are
+ created and compiled when QGLShaderProgram::link() is called.
+
+ \sa QGLShaderProgram::programId()
+*/
+GLuint QGLShader::shaderId() const
+{
+ return d->shader;
+}
+
+#undef ctx
+#define ctx context
+
+class QGLShaderProgramPrivate
+{
+public:
+ QGLShaderProgramPrivate(const QGLContext *ctx)
+ {
+ context = ctx;
+ program = 0;
+ linked = false;
+ inited = false;
+ hasPartialShaders = false;
+ vertexShader = 0;
+ fragmentShader = 0;
+ }
+ ~QGLShaderProgramPrivate()
+ {
+ if (program)
+ glDeleteProgram(program);
+ }
+
+ const QGLContext *context;
+ GLuint program;
+ bool linked;
+ bool inited;
+ bool hasPartialShaders;
+ QString errors;
+ QList<QGLShader *> shaders;
+ QList<QGLShader *> anonShaders;
+ QGLShader *vertexShader;
+ QGLShader *fragmentShader;
+};
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with the current QGLContext.
+
+ \sa isValid(), addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(QGLContext::currentContext());
+}
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with \a context.
+
+ \sa isValid(), addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(context);
+}
+
+/*!
+ Deletes this shader program.
+*/
+QGLShaderProgram::~QGLShaderProgram()
+{
+ delete d;
+}
+
+bool QGLShaderProgram::init()
+{
+ if (d->program || d->inited)
+ return true;
+ d->inited = true;
+ if (!d->context)
+ d->context = QGLContext::currentContext();
+ if (!d->context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(d->context))) {
+ d->program = glCreateProgram();
+ if (!(d->program)) {
+ qWarning() << "QGLShaderProgram: could not create shader program";
+ return false;
+ }
+ return true;
+ } else {
+ qWarning() << "QGLShaderProgram: shader programs are not supported";
+ return false;
+ }
+}
+
+/*!
+ Returns true if this shader program object is valid, false otherwise.
+*/
+bool QGLShaderProgram::isValid() const
+{
+ if (!d->program)
+ return false;
+#if defined(QT_OPENGL_ES_2)
+ return glIsProgram(d->program);
+#else
+ // glIsProgram() may not exist on some systems.
+ return (!glIsProgram || glIsProgram(d->program));
+#endif
+}
+
+/*!
+ Adds a compiled \a shader to this shader program. Returns true
+ if the shader could be added, or false otherwise.
+
+ Ownership of the \a shader object remains with the caller.
+ It will not be deleted when this QGLShaderProgram instance
+ is deleted. This allows the caller to add the same shader
+ to multiple shader programs.
+
+ \sa removeShader(), link(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader *shader)
+{
+ if (!init())
+ return false;
+ if (d->shaders.contains(shader))
+ return true; // Already added to this shader program.
+ if (d->program && shader) {
+ if (!shader->d->compiled)
+ return false;
+ if (!shader->d->isPartial) {
+ if (!shader->d->shader)
+ return false;
+ glAttachShader(d->program, shader->d->shader);
+ } else {
+ d->hasPartialShaders = true;
+ }
+ d->linked = false; // Program needs to be relinked.
+ d->shaders.append(shader);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ will be made available via errors().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), errors(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const char *source)
+{
+ if (!init())
+ return false;
+ QGLShader *shader = new QGLShader(type, this);
+ if (!shader->setSourceCode(source)) {
+ d->errors = shader->errors();
+ delete shader;
+ return false;
+ }
+ d->anonShaders.append(shader);
+ return addShader(shader);
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ will be made available via errors().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), errors(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QByteArray& source)
+{
+ return addShader(type, source.constData());
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ will be made available via errors().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), errors(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QString& source)
+{
+ return addShader(type, source.toLatin1().constData());
+}
+
+/*!
+ Removes \a shader from this shader program. The object is not deleted.
+
+ \sa addShader(), link(), removeAllShaders()
+*/
+void QGLShaderProgram::removeShader(QGLShader *shader)
+{
+ if (d->program && shader && shader->d->shader) {
+ glDetachShader(d->program, shader->d->shader);
+ d->linked = false; // Program needs to be relinked.
+ }
+ d->shaders.removeAll(shader);
+ d->anonShaders.removeAll(shader);
+}
+
+/*!
+ Returns a list of all shaders that have been added to this shader
+ program using addShader().
+
+ \sa addShader(), removeShader()
+*/
+QList<QGLShader *> QGLShaderProgram::shaders() const
+{
+ return d->shaders;
+}
+
+/*!
+ Removes all of the shaders that were added to this program previously.
+ The QGLShader objects for the shaders will not be deleted if they
+ were constructed externally. QGLShader objects that are constructed
+ internally by QGLShaderProgram will be deleted.
+
+ \sa addShader(), removeShader()
+*/
+void QGLShaderProgram::removeAllShaders()
+{
+ foreach (QGLShader *shader, d->shaders) {
+ if (d->program && shader && shader->d->shader)
+ glDetachShader(d->program, shader->d->shader);
+ }
+ foreach (QGLShader *shader, d->anonShaders) {
+ // Delete shader objects that were created anonymously.
+ delete shader;
+ }
+ d->shaders.clear();
+ d->anonShaders.clear();
+ d->linked = false; // Program needs to be relinked.
+}
+
+#if defined(QT_OPENGL_ES_2)
+
+#ifndef GL_PROGRAM_BINARY_LENGTH_OES
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#endif
+#ifndef GL_NUM_PROGRAM_BINARY_FORMATS_OES
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#endif
+#ifndef GL_PROGRAM_BINARY_FORMATS_OES
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#endif
+
+#endif
+
+/*!
+ Returns the program binary associated with this shader program.
+ The numeric identifier of the program binary format is returned
+ in \a format. The \c OES_get_program_binary extension will need
+ to be supported by the system for binary retrieval to succeed.
+
+ Returns an empty QByteArray if the program binary cannot be
+ retrieved on this system, or the shader program has not yet
+ been linked.
+
+ The returned binary can be supplied to setProgramBinary() on the
+ same machine at some future point to reload the program. It contains
+ the compiled code of all of the shaders that were attached to the
+ program at the time programBinary() is called.
+
+ \sa setProgramBinary(), programBinaryFormats()
+*/
+QByteArray QGLShaderProgram::programBinary(int *format) const
+{
+#if defined(QT_OPENGL_ES_2)
+ if (!isLinked())
+ return QByteArray();
+
+ // Get the length of the binary data, bailing out if there is none.
+ GLint length = 0;
+ glGetProgramiv(d->program, GL_PROGRAM_BINARY_LENGTH_OES, &length);
+ if (length <= 0)
+ return QByteArray();
+
+ // Retrieve the binary data.
+ QByteArray binary(length, 0);
+ GLenum binaryFormat;
+ glGetProgramBinaryOES(d->program, length, 0, &binaryFormat, binary.data());
+ if (format)
+ *format = (int)binaryFormat;
+ return binary;
+#else
+ Q_UNUSED(format);
+ return QByteArray();
+#endif
+}
+
+/*!
+ Sets the \a binary for this shader program according to \a format.
+ Returns true if the binary was set, or false if the binary format
+ is not supported or this system does not support program binaries.
+ The program will be linked if the load succeeds.
+
+ \sa programBinary(), programBinaryFormats(), isLinked()
+*/
+bool QGLShaderProgram::setProgramBinary(int format, const QByteArray& binary)
+{
+#if defined(QT_OPENGL_ES_2)
+ // Load the binary and check that it was linked correctly.
+ glProgramBinaryOES(d->program, (GLenum)format,
+ binary.constData(), binary.size());
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->errors = QString();
+ if (value > 1) {
+ char *log = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, log);
+ d->errors = QString::fromLatin1(log);
+ qWarning() << "QGLShaderProgram::setProgramBinary:" << d->errors;
+ delete [] log;
+ }
+ return d->linked;
+#else
+ Q_UNUSED(format);
+ Q_UNUSED(binary);
+ return false;
+#endif
+}
+
+/*!
+ Returns the list of program binary formats that are accepted by
+ this system for use with setProgramBinary().
+
+ \sa programBinary, setProgramBinary()
+*/
+QList<int> QGLShaderProgram::programBinaryFormats()
+{
+#if defined(QT_OPENGL_ES_2)
+ GLint count = 0;
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &count);
+ if (count <= 0)
+ return QList<int>();
+ QVector<int> list;
+ list.resize(count);
+ glGetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, list.data());
+ return list.toList();
+#else
+ return QList<int>();
+#endif
+}
+
+/*!
+ Links together the shaders that were added to this program with
+ addShader(). Returns true if the link was successful or
+ false otherwise. If the link failed, the error messages can
+ be retrieved with errors().
+
+ Subclasses can override this function to initialize attributes
+ and uniform variables for use in specific shader programs.
+
+ If the shader program was already linked, calling this
+ function again will force it to be re-linked.
+
+ \sa addShader(), errors()
+*/
+bool QGLShaderProgram::link()
+{
+ if (!d->program)
+ return false;
+ if (d->hasPartialShaders) {
+ // Compile the partial vertex and fragment shaders.
+ QByteArray vertexSource;
+ QByteArray fragmentSource;
+ foreach (QGLShader *shader, d->shaders) {
+ if (shader->shaderType() == QGLShader::PartialVertexShader)
+ vertexSource += shader->sourceCode();
+ else if (shader->shaderType() == QGLShader::PartialFragmentShader)
+ fragmentSource += shader->sourceCode();
+ }
+ if (vertexSource.isEmpty()) {
+ if (d->vertexShader) {
+ glDetachShader(d->program, d->vertexShader->d->shader);
+ delete d->vertexShader;
+ d->vertexShader = 0;
+ }
+ } else {
+ if (!d->vertexShader) {
+ d->vertexShader =
+ new QGLShader(QGLShader::VertexShader, this);
+ }
+ if (!d->vertexShader->setSourceCode(vertexSource)) {
+ d->errors = d->vertexShader->errors();
+ return false;
+ }
+ glAttachShader(d->program, d->vertexShader->d->shader);
+ }
+ if (fragmentSource.isEmpty()) {
+ if (d->fragmentShader) {
+ glDetachShader(d->program, d->fragmentShader->d->shader);
+ delete d->fragmentShader;
+ d->fragmentShader = 0;
+ }
+ } else {
+ if (!d->fragmentShader) {
+ d->fragmentShader =
+ new QGLShader(QGLShader::FragmentShader, this);
+ }
+ if (!d->fragmentShader->setSourceCode(fragmentSource)) {
+ d->errors = d->fragmentShader->errors();
+ return false;
+ }
+ glAttachShader(d->program, d->fragmentShader->d->shader);
+ }
+ }
+ glLinkProgram(d->program);
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->errors = QString();
+ if (value > 1) {
+ char *log = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, log);
+ d->errors = QString::fromLatin1(log);
+ qWarning() << "QGLShaderProgram::link:" << d->errors;
+ delete [] log;
+ }
+ return d->linked;
+}
+
+/*!
+ Returns true if this shader program has been linked; false otherwise.
+
+ \sa link()
+*/
+bool QGLShaderProgram::isLinked() const
+{
+ return d->linked;
+}
+
+/*!
+ Returns the errors that occurred during the last link()
+ or addShader() with explicitly specified source code.
+
+ \sa link()
+*/
+QString QGLShaderProgram::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Enable use of this shader program in the currently active QGLContext.
+ Returns true if the program was successfully enabled; false
+ otherwise. If the shader program has not yet been linked,
+ or it needs to be re-linked, this function will call link().
+
+ \sa link(), disable()
+*/
+bool QGLShaderProgram::enable()
+{
+ if (!d->program)
+ return false;
+ if (!d->linked && !link())
+ return false;
+ glUseProgram(d->program);
+ return true;
+}
+
+/*!
+ Disables this shader program in the currently active QGLContext.
+ This is equivalent to calling \c{glUseProgram(0)}.
+
+ \sa enable()
+*/
+void QGLShaderProgram::disable()
+{
+#if defined(QT_OPENGL_ES_2)
+ glUseProgram(0);
+#else
+ if (glUseProgram)
+ glUseProgram(0);
+#endif
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader program.
+
+ \sa QGLShader::shaderId()
+*/
+GLuint QGLShaderProgram::programId() const
+{
+ return d->program;
+}
+
+/*!
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const char *name, int location)
+{
+ glBindAttribLocation(d->program, location, name);
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.constData());
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QString& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.toLatin1().constData());
+}
+
+/*!
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetAttribLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::attributeLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QByteArray& name) const
+{
+ return attributeLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QString& name) const
+{
+ return attributeLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glVertexAttrib1fv(location, &value);
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glVertexAttrib2fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y)
+{
+ setAttributeValue(attributeLocation(name), x, y);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glVertexAttrib3fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setAttributeValue(attributeLocation(name), x, y, z);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setAttributeValue(attributeLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glVertexAttrib2fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glVertexAttrib3fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glVertexAttrib4fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QColor& value)
+{
+ if (location != -1) {
+ GLfloat values[4] = {value.redF(), value.greenF(), value.blueF(), value.alphaF()};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QColor& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, const GLfloat *values, int columns, int rows)
+{
+ if (rows < 1 || rows > 4) {
+ qWarning() << "QGLShaderProgram::setAttributeValue: rows" << rows << "not supported";
+ return;
+ }
+ if (location != -1) {
+ while (columns-- > 0) {
+ if (rows == 1)
+ glVertexAttrib1fv(location, values);
+ else if (rows == 2)
+ glVertexAttrib2fv(location, values);
+ else if (rows == 3)
+ glVertexAttrib3fv(location, values);
+ else
+ glVertexAttrib4fv(location, values);
+ values += rows;
+ ++location;
+ }
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, const GLfloat *values, int columns, int rows)
+{
+ setAttributeValue(attributeLocation(name), values, columns, rows);
+}
+
+/*!
+ Sets an array of vertex \a values on the attribute at \a location
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const GLfloat *values, int size, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 2D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector2D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 3D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector3D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 4D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector4D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ \overload
+
+ Sets an array of vertex \a values on the attribute called \a name
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, size, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 2D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector2D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 3D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector3D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 4D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector4D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ Disables the vertex array at \a location in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(int location)
+{
+ if (location != -1)
+ glDisableVertexAttribArray(location);
+}
+
+/*!
+ \overload
+
+ Disables the vertex array called \a name in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(const char *name)
+{
+ disableAttributeArray(attributeLocation(name));
+}
+
+/*!
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetUniformLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::uniformLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QByteArray& name) const
+{
+ return uniformLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QString& name) const
+{
+ return uniformLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glUniform1fv(location, 1, &value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+ This function must be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLint value)
+{
+ if (location != -1)
+ glUniform1i(location, value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value. This function must be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLint value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y)
+{
+ setUniformValue(uniformLocation(name), x, y);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glUniform3fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setUniformValue(uniformLocation(name), x, y, z);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setUniformValue(uniformLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glUniform2fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector2D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glUniform3fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector3D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glUniform4fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector4D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QColor& color)
+{
+ if (location != -1) {
+ GLfloat values[4] = {color.redF(), color.greenF(), color.blueF(), color.alphaF()};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QColor& color)
+{
+ setUniformValue(uniformLocation(name), color);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
+{
+ if (location != -1)
+ glUniformMatrix2fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
+{
+ if (location != -1)
+ glUniformMatrix3fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4])
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(location, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue(int location, const QTransform& value)
+{
+ if (location != -1) {
+ GLfloat mat[3][3] = {
+ {value.m11(), value.m12(), value.m13()},
+ {value.m21(), value.m22(), value.m23()},
+ {value.m31(), value.m32(), value.m33()}
+ };
+ glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(name, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, const QTransform& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. This overload
+ must be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count)
+{
+ if (location != -1)
+ glUniform1iv(location, count, values);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. This overload
+ must be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLint *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int size)
+{
+ if (location != -1) {
+ if (size == 1)
+ glUniform1fv(location, count, values);
+ else if (size == 2)
+ glUniform2fv(location, count, values);
+ else if (size == 3)
+ glUniform3fv(location, count, values);
+ else if (size == 4)
+ glUniform4fv(location, count, values);
+ else
+ qWarning() << "QGLShaderProgram::setUniformValue: size" << size << "not supported";
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLfloat *values, int count, int size)
+{
+ setUniformValueArray(uniformLocation(name), values, count, size);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count)
+{
+ if (location != -1)
+ glUniform2fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count)
+{
+ if (location != -1)
+ glUniform3fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count)
+{
+ if (location != -1)
+ glUniform4fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+// We may have to repack matrix arrays if the matrix types
+// contain additional flag bits. Especially QMatrix4x4.
+#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ func(location, count, GL_FALSE, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ func(location, count, GL_FALSE, temp.constData()); \
+ }
+#if !defined(QT_OPENGL_ES_2)
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ if (func) \
+ func(location, count, GL_FALSE, values->constData()); \
+ else \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ if (func) \
+ func(location, count, GL_FALSE, temp.constData()); \
+ else \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#else
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#endif
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x3fv, glUniform3fv, location, values, count,
+ QMatrix2x3, 2, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x4fv, glUniform4fv, location, values, count,
+ QMatrix2x4, 2, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x2fv, glUniform2fv, location, values, count,
+ QMatrix3x2, 3, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x4fv, glUniform4fv, location, values, count,
+ QMatrix3x4, 3, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x2fv, glUniform2fv, location, values, count,
+ QMatrix4x2, 4, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x3fv, glUniform3fv, location, values, count,
+ QMatrix4x3, 4, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Returns true if shader programs written in the OpenGL Shading
+ Language (GLSL) are supported on this system; false otherwise.
+
+ The \a context is used to resolve the GLSL extensions.
+ If \a context is null, then QGLContext::currentContext() is used.
+*/
+bool QGLShaderProgram::hasShaderPrograms(const QGLContext *context)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ return qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
+#else
+ Q_UNUSED(context);
+ return true;
+#endif
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
new file mode 100644
index 0000000..ec6faaf
--- /dev/null
+++ b/src/opengl/qglshaderprogram.h
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLSHADERPROGRAM_H
+#define QGLSHADERPROGRAM_H
+
+#include <QtOpenGL/qgl.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qmatrix4x4.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+#if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_GL_FIXED_PREFERRED)
+
+class QGLShaderProgram;
+class QGLShaderPrivate;
+
+class Q_OPENGL_EXPORT QGLShader : public QObject
+{
+ Q_OBJECT
+public:
+ enum ShaderType
+ {
+ VertexShader,
+ FragmentShader,
+ PartialVertexShader,
+ PartialFragmentShader
+ };
+
+ explicit QGLShader(QGLShader::ShaderType type, QObject *parent = 0);
+ explicit QGLShader(const QString& fileName, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, QObject *parent = 0);
+ QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShader();
+
+ bool isValid() const;
+
+ QGLShader::ShaderType shaderType() const;
+
+ bool setSourceCode(const char *source);
+ bool setSourceCode(const QByteArray& source);
+ bool setSourceCode(const QString& source);
+ bool setSourceCodeFile(const QString& fileName);
+
+ bool setBinaryCode(GLenum format, const void *binary, int length);
+ bool setBinaryCode(QGLShader& otherShader, GLenum format, const void *binary, int length);
+
+ static QList<GLenum> shaderBinaryFormats();
+
+ QByteArray sourceCode() const;
+
+ bool isCompiled() const;
+ QString errors() const;
+
+ GLuint shaderId() const;
+
+private:
+ QGLShaderPrivate *d;
+
+ friend class QGLShaderProgram;
+
+ Q_DISABLE_COPY(QGLShader);
+};
+
+class QGLShaderProgramPrivate;
+
+class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QGLShaderProgram(QObject *parent = 0);
+ explicit QGLShaderProgram(const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShaderProgram();
+
+ bool isValid() const;
+
+ bool addShader(QGLShader *shader);
+ void removeShader(QGLShader *shader);
+ QList<QGLShader *> shaders() const;
+
+ bool addShader(QGLShader::ShaderType type, const char *source);
+ bool addShader(QGLShader::ShaderType type, const QByteArray& source);
+ bool addShader(QGLShader::ShaderType type, const QString& source);
+
+ void removeAllShaders();
+
+ QByteArray programBinary(int *format) const;
+ bool setProgramBinary(int format, const QByteArray& binary);
+ static QList<int> programBinaryFormats();
+
+ virtual bool link();
+ bool isLinked() const;
+ QString errors() const;
+
+ bool enable();
+ void disable();
+
+ GLuint programId() const;
+
+ void bindAttributeLocation(const char *name, int location);
+ void bindAttributeLocation(const QByteArray& name, int location);
+ void bindAttributeLocation(const QString& name, int location);
+
+ int attributeLocation(const char *name) const;
+ int attributeLocation(const QByteArray& name) const;
+ int attributeLocation(const QString& name) const;
+
+ void setAttributeValue(int location, GLfloat value);
+ void setAttributeValue(int location, GLfloat x, GLfloat y);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(int location, const QVector2D& value);
+ void setAttributeValue(int location, const QVector3D& value);
+ void setAttributeValue(int location, const QVector4D& value);
+ void setAttributeValue(int location, const QColor& value);
+ void setAttributeValue(int location, const GLfloat *values, int columns, int rows);
+
+ void setAttributeValue(const char *name, GLfloat value);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(const char *name, const QVector2D& value);
+ void setAttributeValue(const char *name, const QVector3D& value);
+ void setAttributeValue(const char *name, const QVector4D& value);
+ void setAttributeValue(const char *name, const QColor& value);
+ void setAttributeValue(const char *name, const GLfloat *values, int columns, int rows);
+
+ void setAttributeArray
+ (int location, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector4D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector4D *values, int stride = 0);
+ void disableAttributeArray(int location);
+ void disableAttributeArray(const char *name);
+
+ int uniformLocation(const char *name) const;
+ int uniformLocation(const QByteArray& name) const;
+ int uniformLocation(const QString& name) const;
+
+ void setUniformValue(int location, GLfloat value);
+ void setUniformValue(int location, GLint value);
+ void setUniformValue(int location, GLfloat x, GLfloat y);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(int location, const QVector2D& value);
+ void setUniformValue(int location, const QVector3D& value);
+ void setUniformValue(int location, const QVector4D& value);
+ void setUniformValue(int location, const QColor& color);
+ void setUniformValue(int location, const QMatrix2x2& value);
+ void setUniformValue(int location, const QMatrix2x3& value);
+ void setUniformValue(int location, const QMatrix2x4& value);
+ void setUniformValue(int location, const QMatrix3x2& value);
+ void setUniformValue(int location, const QMatrix3x3& value);
+ void setUniformValue(int location, const QMatrix3x4& value);
+ void setUniformValue(int location, const QMatrix4x2& value);
+ void setUniformValue(int location, const QMatrix4x3& value);
+ void setUniformValue(int location, const QMatrix4x4& value);
+ void setUniformValue(int location, const GLfloat value[4][4]);
+ void setUniformValue(int location, const QTransform& value);
+
+ void setUniformValue(const char *name, GLfloat value);
+ void setUniformValue(const char *name, GLint value);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(const char *name, const QVector2D& value);
+ void setUniformValue(const char *name, const QVector3D& value);
+ void setUniformValue(const char *name, const QVector4D& value);
+ void setUniformValue(const char *name, const QColor& color);
+ void setUniformValue(const char *name, const QMatrix2x2& value);
+ void setUniformValue(const char *name, const QMatrix2x3& value);
+ void setUniformValue(const char *name, const QMatrix2x4& value);
+ void setUniformValue(const char *name, const QMatrix3x2& value);
+ void setUniformValue(const char *name, const QMatrix3x3& value);
+ void setUniformValue(const char *name, const QMatrix3x4& value);
+ void setUniformValue(const char *name, const QMatrix4x2& value);
+ void setUniformValue(const char *name, const QMatrix4x3& value);
+ void setUniformValue(const char *name, const QMatrix4x4& value);
+ void setUniformValue(const char *name, const GLfloat value[4][4]);
+ void setUniformValue(const char *name, const QTransform& value);
+
+ void setUniformValueArray(int location, const GLfloat *values, int count, int size);
+ void setUniformValueArray(int location, const GLint *values, int count);
+ void setUniformValueArray(int location, const QVector2D *values, int count);
+ void setUniformValueArray(int location, const QVector3D *values, int count);
+ void setUniformValueArray(int location, const QVector4D *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x4 *values, int count);
+
+ void setUniformValueArray(const char *name, const GLfloat *values, int count, int size);
+ void setUniformValueArray(const char *name, const GLint *values, int count);
+ void setUniformValueArray(const char *name, const QVector2D *values, int count);
+ void setUniformValueArray(const char *name, const QVector3D *values, int count);
+ void setUniformValueArray(const char *name, const QVector4D *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x4 *values, int count);
+
+ static bool hasShaderPrograms(const QGLContext *context = 0);
+
+private:
+ QGLShaderProgramPrivate *d;
+
+ Q_DISABLE_COPY(QGLShaderProgram);
+
+ bool init();
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif