summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/glgc_shader_source.h289
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp465
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h388
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h383
-rw-r--r--src/opengl/gl2paintengineex/qglpexshadermanager.cpp450
-rw-r--r--src/opengl/gl2paintengineex/qglpexshadermanager_p.h156
-rw-r--r--src/opengl/gl2paintengineex/qglshader.cpp1
-rw-r--r--src/opengl/gl2paintengineex/qglshader_p.h3
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp278
-rw-r--r--src/opengl/opengl.pro13
-rw-r--r--src/opengl/qglextensions.cpp214
-rw-r--r--src/opengl/qglextensions_p.h134
-rw-r--r--src/opengl/qglpixmapfilter.cpp165
-rw-r--r--src/opengl/qglpixmapfilter_p.h29
-rw-r--r--src/opengl/qglshaderprogram.cpp2960
-rw-r--r--src/opengl/qglshaderprogram.h295
25 files changed, 5142 insertions, 2114 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/glgc_shader_source.h b/src/opengl/gl2paintengineex/glgc_shader_source.h
deleted file mode 100644
index 5b9d28b..0000000
--- a/src/opengl/gl2paintengineex/glgc_shader_source.h
+++ /dev/null
@@ -1,289 +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 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 GLGC_SHADER_SOURCE_H
-#define GLGC_SHADER_SOURCE_H
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(OpenGL)
-
-static const char* qglslImageVertexShader = "\
- attribute highp vec4 inputVertex; \
- attribute lowp vec2 textureCoord; \
- uniform highp mat4 pmvMatrix; \
- varying lowp vec2 fragTextureCoord; \
- void main(void) \
- {\
- gl_Position = pmvMatrix * inputVertex;\
- fragTextureCoord = textureCoord; \
- }";
-
-static const char* qglslImageFragmentShader = "\
- varying lowp vec2 fragTextureCoord;\
- uniform sampler2D textureSampler;\
- uniform lowp float opacity; \
- void main(void) \
- {\
- gl_FragColor = texture2D(textureSampler, fragTextureCoord) * opacity; \
- }";
-
-static const char* qglslTextFragmentShader = "\
- varying lowp vec2 fragTextureCoord;\
- uniform mediump vec4 fragmentColor;\
- uniform sampler2D textureSampler;\
- void main(void) \
- {\
- highp vec4 tex = texture2D(textureSampler, fragTextureCoord); \
- tex = fragmentColor * tex.r; \
- gl_FragColor = tex; \
- }";
-
-static const char* qglslDefaultVertexShader = "\
- attribute highp vec4 inputVertex;\
- uniform highp mat4 pmvMatrix;\
- void main(void)\
- {\
- gl_Position = pmvMatrix * inputVertex;\
- }";
-
-static const char* qglslSimpleFragmentShader = "\
- void main (void)\
- {\
- gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\
- }";
-
-
-/**** FRAGMENT SHADER MAIN FUNCTIONS ****/
-// NOTE: Currently, the engine assumes brushes return colors already in pre-multiplied
-// format. However, this may change if we add support for non-premultiplied
-
-static const char* qglslNoOpacityFragmentShaderMain = "\n\
- mediump vec4 brush();\
- void main (void)\
- {\
- gl_FragColor = brush();\
- }\n";
-
-static const char* qglslFragmentShaderMain = "\n\
- mediump vec4 brush();\
- uniform lowp float opacity; \
- void main (void)\
- {\
- gl_FragColor = brush() * opacity;\
- }\n";
-
-
-
-/**** BRUSH SHADERS ****/
-
-// This should never actually be used
-static const char* qglslNoBrushFragmentShader = "\n\
- mediump vec4 brush() { \
- discard; \
- return vec4(1.0, 0.8, 0.8, 1.0);\
- }\n";
-
-// Solid Fill Brush
-static const char* qglslSolidBrushFragmentShader = "\n\
- uniform mediump vec4 fragmentColor; \
- mediump vec4 brush() { \
- return fragmentColor;\
- }\n";
-
-// Texture Brush
-static const char* qglslTextureBrushVertexShader = "\
- attribute highp vec4 inputVertex; \
- uniform highp mat4 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform mediump vec2 invertedTextureSize; \
- uniform mediump mat3 brushTransform; \
- varying mediump vec2 texCoords; \
- void main(void) { \
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- texCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \
- texCoords.y = -texCoords.y; \
- }";
-
-static const char* qglslTextureBrushFragmentShader = "\n\
- varying mediump vec2 texCoords;\
- uniform sampler2D brushTexture;\
- mediump vec4 brush() { \
- return texture2D(brushTexture, texCoords); \
- }\n";
-
-
-// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
-static const char* qglslPatternBrushVertexShader = "\
- attribute highp vec4 inputVertex; \
- uniform highp mat4 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform mediump vec2 invertedTextureSize; \
- uniform mediump mat3 brushTransform; \
- varying mediump vec2 texCoords; \
- void main(void) { \
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- texCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \
- texCoords.y = -texCoords.y; \
- }";
-
-static const char* qglslPatternBrushFragmentShader = "\n\
- uniform sampler2D brushTexture;\
- uniform lowp vec4 patternColor; \
- varying mediump vec2 texCoords;\
- mediump vec4 brush() { \
- return patternColor * texture2D(brushTexture, texCoords).r; \
- }\n";
-
-
-// Linear Gradient Brush
-static const char* qglslLinearGradientBrushVertexShader = "\
- attribute highp vec4 inputVertex; \
- uniform highp mat4 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform highp vec3 linearData; \
- uniform mediump mat3 brushTransform; \
- varying mediump float index ; \
- void main() { \
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \
- }";
-
-static const char* qglslLinearGradientBrushFragmentShader = "\n\
- uniform sampler2D brushTexture; \
- varying mediump float index; \
- mediump vec4 brush() { \
- mediump vec2 val = vec2(index, 0.5); \
- return texture2D(brushTexture, val); \
- }\n";
-
-
-static const char* qglslRadialGradientBrushVertexShader = "\
- attribute highp vec4 inputVertex;\
- uniform highp mat4 pmvMatrix;\
- uniform mediump vec2 halfViewportSize; \
- uniform highp mat3 brushTransform; \
- uniform highp vec2 fmp; \
- varying highp float b; \
- varying highp vec2 A; \
- void main(void) \
- {\
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- A = hTexCoords.xy * invertedHTexCoordsZ; \
- b = 2.0 * fmp * (A.x + A.y); \
-\
- }";
-
-static const char* qglslRadialGradientBrushFragmentShader = "\n\
- uniform sampler2D brushTexture; \
- uniform highp float fmp2_m_radius2; \
- uniform highp float inverse_2_fmp2_m_radius2; \
- varying highp float b; \
- varying highp vec2 A; \
-\
- mediump vec4 brush() { \
- highp float c = -dot(A, A); \
- highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \
- return texture2D(brushTexture, val); \
- }\n";
-
-static const char* qglslConicalGradientBrushVertexShader = "\
- attribute highp vec4 inputVertex;\
- uniform highp mat4 pmvMatrix;\
- uniform mediump vec2 halfViewportSize; \
- uniform highp mat3 brushTransform; \
- varying highp vec2 A; \
- void main(void)\
- {\
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- A = hTexCoords.xy * invertedHTexCoordsZ; \
- }";
-
-static const char* qglslConicalGradientBrushFragmentShader = "\n\
- #define INVERSE_2PI 0.1591549430918953358 \n\
- uniform sampler2D brushTexture; \
- uniform mediump float angle; \
- varying highp vec2 A; \
- mediump vec4 brush() { \
- if (abs(A.y) == abs(A.x)) \
- A.y += 0.002; \
- highp float t = (atan2(-A.y, A.x) + angle) * INVERSE_2PI; \
- return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \
- }\n";
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // GLGC_SHADER_SOURCE_H
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
new file mode 100644
index 0000000..a4d8b77
--- /dev/null
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -0,0 +1,465 @@
+/****************************************************************************
+**
+** 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 "qglengineshadermanager_p.h"
+#include "qglengineshadersource_p.h"
+
+#if defined(QT_DEBUG)
+#include <QMetaEnum>
+#endif
+
+
+const char* QGLEngineShaderManager::qglEngineShaderSourceCode[] = {
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0
+};
+
+QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
+ : ctx(context),
+ shaderProgNeedsChanging(true),
+ srcPixelType(Qt::NoBrush),
+ useGlobalOpacity(false),
+ maskType(NoMask),
+ useTextureCoords(false),
+ compositionMode(QPainter::CompositionMode_SourceOver),
+ simpleShaderProg(0),
+ currentShaderProg(0)
+{
+ memset(compiledShaders, 0, sizeof(compiledShaders));
+
+/*
+ Rather than having the shader source array statically initialised, it is initialised
+ here instead. This is to allow new shader names to be inserted or existing names moved
+ around without having to change the order of the glsl strings. It is hoped this will
+ make future hard-to-find runtime bugs more obvious and generally give more solid code.
+*/
+ static bool qglEngineShaderSourceCodePopulated = false;
+ if (!qglEngineShaderSourceCodePopulated) {
+
+ const char** code = qglEngineShaderSourceCode; // shortcut
+
+ code[MainVertexShader] = qglslMainVertexShader;
+ code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
+
+ code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader;
+ code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader;
+ code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader;
+ code[PositionWithConicalGradientBrushVertexShader] = qglslPositionWithConicalGradientBrushVertexShader;
+ code[PositionWithRadialGradientBrushVertexShader] = qglslPositionWithRadialGradientBrushVertexShader;
+ code[PositionWithTextureBrushVertexShader] = qglslPositionWithTextureBrushVertexShader;
+ code[AffinePositionWithPatternBrushVertexShader] = qglslAffinePositionWithPatternBrushVertexShader;
+ code[AffinePositionWithLinearGradientBrushVertexShader] = qglslAffinePositionWithLinearGradientBrushVertexShader;
+ code[AffinePositionWithConicalGradientBrushVertexShader] = qglslAffinePositionWithConicalGradientBrushVertexShader;
+ code[AffinePositionWithRadialGradientBrushVertexShader] = qglslAffinePositionWithRadialGradientBrushVertexShader;
+ code[AffinePositionWithTextureBrushVertexShader] = qglslAffinePositionWithTextureBrushVertexShader;
+
+ code[MainFragmentShader_CMO] = qglslMainFragmentShader_CMO;
+ code[MainFragmentShader_CM] = qglslMainFragmentShader_CM;
+ code[MainFragmentShader_MO] = qglslMainFragmentShader_MO;
+ code[MainFragmentShader_M] = qglslMainFragmentShader_M;
+ code[MainFragmentShader_CO] = qglslMainFragmentShader_CO;
+ code[MainFragmentShader_C] = qglslMainFragmentShader_C;
+ code[MainFragmentShader_O] = qglslMainFragmentShader_O;
+ code[MainFragmentShader] = qglslMainFragmentShader;
+
+ code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
+ code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader;
+ code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader;
+ code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader;
+ code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader;
+ code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader;
+ code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader;
+ code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader;
+ code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader;
+
+ code[MaskFragmentShader] = qglslMaskFragmentShader;
+ code[RgbMaskFragmentShader] = ""; //###
+ code[RgbMaskWithGammaFragmentShader] = ""; //###
+
+ code[MultiplyCompositionModeFragmentShader] = ""; //###
+ code[ScreenCompositionModeFragmentShader] = ""; //###
+ code[OverlayCompositionModeFragmentShader] = ""; //###
+ code[DarkenCompositionModeFragmentShader] = ""; //###
+ code[LightenCompositionModeFragmentShader] = ""; //###
+ code[ColorDodgeCompositionModeFragmentShader] = ""; //###
+ code[ColorBurnCompositionModeFragmentShader] = ""; //###
+ code[HardLightCompositionModeFragmentShader] = ""; //###
+ code[SoftLightCompositionModeFragmentShader] = ""; //###
+ code[DifferenceCompositionModeFragmentShader] = ""; //###
+ code[ExclusionCompositionModeFragmentShader] = ""; //###
+
+#if defined(QT_DEBUG)
+ // Check that all the elements have been filled:
+ for (int i = 0; i < TotalShaderCount; ++i) {
+ if (qglEngineShaderSourceCode[i] == 0) {
+ int enumIndex = staticMetaObject.indexOfEnumerator("ShaderName");
+ QMetaEnum m = staticMetaObject.enumerator(enumIndex);
+
+ qCritical() << "qglEngineShaderSourceCode: Source for" << m.valueToKey(i)
+ << "(shader" << i << ") missing!";
+ }
+ }
+#endif
+ qglEngineShaderSourceCodePopulated = true;
+ }
+
+ // Compile up the simple shader:
+ simpleShaderProg = new QGLShaderProgram(ctx, this);
+ compileNamedShader(MainVertexShader, QGLShader::PartialVertexShader);
+ compileNamedShader(PositionOnlyVertexShader, QGLShader::PartialVertexShader);
+ compileNamedShader(MainFragmentShader, QGLShader::PartialFragmentShader);
+ compileNamedShader(ShockingPinkSrcFragmentShader, QGLShader::PartialFragmentShader);
+ simpleShaderProg->addShader(compiledShaders[MainVertexShader]);
+ simpleShaderProg->addShader(compiledShaders[PositionOnlyVertexShader]);
+ simpleShaderProg->addShader(compiledShaders[MainFragmentShader]);
+ simpleShaderProg->addShader(compiledShaders[ShockingPinkSrcFragmentShader]);
+ simpleShaderProg->link();
+ if (!simpleShaderProg->isValid()) {
+ qCritical() << "Errors linking simple shader:"
+ << simpleShaderProg->errors();
+ }
+}
+
+QGLEngineShaderManager::~QGLEngineShaderManager()
+{
+ //###
+}
+
+
+
+
+
+void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform transform)
+{
+ Q_UNUSED(transform); // Currently ignored
+}
+
+void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
+{
+ srcPixelType = style;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
+{
+ srcPixelType = type;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setTextureCoordsEnabled(bool enabled)
+{
+ useTextureCoords = enabled;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setUseGlobalOpacity(bool useOpacity)
+{
+ useGlobalOpacity = useOpacity;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setMaskType(MaskType type)
+{
+ maskType = type;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode)
+{
+ compositionMode = mode;
+ shaderProgNeedsChanging = true; //###
+}
+
+bool QGLEngineShaderManager::shaderProgramDirty()
+{
+ return shaderProgNeedsChanging;
+}
+
+QGLShaderProgram* QGLEngineShaderManager::currentProgram()
+{
+ return currentShaderProg;
+}
+
+QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
+{
+ return simpleShaderProg;
+}
+
+
+
+
+// Select & use the correct shader program using the current state
+void QGLEngineShaderManager::useCorrectShaderProg()
+{
+ QGLEngineShaderProg requiredProgram;
+ requiredProgram.program = 0;
+
+ // Choose vertex shader main function
+ QGLEngineShaderManager::ShaderName mainVertexShaderName = InvalidShaderName;
+ if (useTextureCoords)
+ mainVertexShaderName = MainWithTexCoordsVertexShader;
+ else
+ mainVertexShaderName = MainVertexShader;
+ compileNamedShader(mainVertexShaderName, QGLShader::PartialVertexShader);
+ requiredProgram.mainVertexShader = compiledShaders[mainVertexShaderName];
+
+ // Choose vertex shader shader position function (which typically also sets
+ // varyings) and the source pixel (srcPixel) fragment shader function:
+ QGLEngineShaderManager::ShaderName positionVertexShaderName = InvalidShaderName;
+ QGLEngineShaderManager::ShaderName srcPixelFragShaderName = InvalidShaderName;
+ bool isAffine = brushTransform.isAffine();
+ if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
+ if (isAffine)
+ positionVertexShaderName = AffinePositionWithPatternBrushVertexShader;
+ else
+ positionVertexShaderName = PositionWithPatternBrushVertexShader;
+
+ srcPixelFragShaderName = PatternBrushSrcFragmentShader;
+ }
+ else switch (srcPixelType) {
+ default:
+ case Qt::NoBrush:
+ qCritical("QGLEngineShaderManager::useCorrectShaderProg() - I'm scared, Qt::NoBrush style is set");
+ break;
+ case QGLEngineShaderManager::ImageSrc:
+ srcPixelFragShaderName = ImageSrcFragmentShader;
+ positionVertexShaderName = PositionOnlyVertexShader;
+ break;
+ case QGLEngineShaderManager::NonPremultipliedImageSrc:
+ srcPixelFragShaderName = NonPremultipliedImageSrcFragmentShader;
+ positionVertexShaderName = PositionOnlyVertexShader;
+ break;
+ case Qt::SolidPattern:
+ srcPixelFragShaderName = SolidBrushSrcFragmentShader;
+ positionVertexShaderName = PositionOnlyVertexShader;
+ break;
+ case Qt::LinearGradientPattern:
+ srcPixelFragShaderName = LinearGradientBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithLinearGradientBrushVertexShader
+ : PositionWithLinearGradientBrushVertexShader;
+ break;
+ case Qt::ConicalGradientPattern:
+ srcPixelFragShaderName = ConicalGradientBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithConicalGradientBrushVertexShader
+ : PositionWithConicalGradientBrushVertexShader;
+ break;
+ case Qt::RadialGradientPattern:
+ srcPixelFragShaderName = RadialGradientBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithRadialGradientBrushVertexShader
+ : PositionWithRadialGradientBrushVertexShader;
+ break;
+ case Qt::TexturePattern:
+ srcPixelFragShaderName = TextureBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithTextureBrushVertexShader
+ : PositionWithTextureBrushVertexShader;
+ break;
+ };
+ compileNamedShader(positionVertexShaderName, QGLShader::PartialVertexShader);
+ compileNamedShader(srcPixelFragShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.positionVertexShader = compiledShaders[positionVertexShaderName];
+ requiredProgram.srcPixelFragShader = compiledShaders[srcPixelFragShaderName];
+
+
+ const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
+ const bool hasMask = maskType != QGLEngineShaderManager::NoMask;
+
+ // Choose fragment shader main function:
+ QGLEngineShaderManager::ShaderName mainFragShaderName;
+
+ if (hasCompose && hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_CMO;
+ if (hasCompose && hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_CM;
+ if (!hasCompose && hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_MO;
+ if (!hasCompose && hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_M;
+ if (hasCompose && !hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_CO;
+ if (hasCompose && !hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_C;
+ if (!hasCompose && !hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_O;
+ if (!hasCompose && !hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader;
+
+ compileNamedShader(mainFragShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.mainFragShader = compiledShaders[mainFragShaderName];
+
+ if (hasMask) {
+ QGLEngineShaderManager::ShaderName maskShaderName = QGLEngineShaderManager::InvalidShaderName;
+ if (maskType == PixelMask)
+ maskShaderName = MaskFragmentShader;
+ else if (maskType == SubPixelMask)
+ maskShaderName = RgbMaskFragmentShader;
+ else if (maskType == SubPixelWithGammaMask)
+ maskShaderName = RgbMaskWithGammaFragmentShader;
+ else
+ qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
+
+ compileNamedShader(maskShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.maskFragShader = compiledShaders[maskShaderName];
+ }
+ else
+ requiredProgram.maskFragShader = 0;
+
+ if (hasCompose) {
+ QGLEngineShaderManager::ShaderName compositionShaderName = QGLEngineShaderManager::InvalidShaderName;
+ switch (compositionMode) {
+ case QPainter::CompositionMode_Multiply:
+ compositionShaderName = MultiplyCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Screen:
+ compositionShaderName = ScreenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Overlay:
+ compositionShaderName = OverlayCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Darken:
+ compositionShaderName = DarkenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Lighten:
+ compositionShaderName = LightenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorDodge:
+ compositionShaderName = ColorDodgeCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorBurn:
+ compositionShaderName = ColorBurnCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_HardLight:
+ compositionShaderName = HardLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_SoftLight:
+ compositionShaderName = SoftLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Difference:
+ compositionShaderName = DifferenceCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Exclusion:
+ compositionShaderName = ExclusionCompositionModeFragmentShader;
+ break;
+ default:
+ qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
+ }
+ compileNamedShader(compositionShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.compositionFragShader = compiledShaders[compositionShaderName];
+ }
+ else
+ requiredProgram.compositionFragShader = 0;
+
+
+ // At this point, requiredProgram is fully populated so try to find the program in the cache
+ foreach (const QGLEngineShaderProg &prog, cachedPrograms) {
+ if ( (prog.mainVertexShader == requiredProgram.mainVertexShader)
+ && (prog.positionVertexShader == requiredProgram.positionVertexShader)
+ && (prog.mainFragShader == requiredProgram.mainFragShader)
+ && (prog.srcPixelFragShader == requiredProgram.srcPixelFragShader)
+ && (prog.compositionFragShader == requiredProgram.compositionFragShader) )
+ {
+ currentShaderProg = prog.program;
+ currentShaderProg->enable();
+ shaderProgNeedsChanging = false;
+ return;
+ }
+ }
+
+ // Shader program not found in cache, create it now.
+ requiredProgram.program = new QGLShaderProgram(ctx, this);
+ requiredProgram.program->addShader(requiredProgram.mainVertexShader);
+ requiredProgram.program->addShader(requiredProgram.positionVertexShader);
+ requiredProgram.program->addShader(requiredProgram.mainFragShader);
+ requiredProgram.program->addShader(requiredProgram.srcPixelFragShader);
+ requiredProgram.program->addShader(requiredProgram.maskFragShader);
+ requiredProgram.program->addShader(requiredProgram.compositionFragShader);
+
+ // We have to bind the vertex attribute names before the program is linked:
+ requiredProgram.program->bindAttributeLocation("inputVertex", QT_VERTEX_COORDS_ATTR);
+ if (useTextureCoords)
+ requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+
+ requiredProgram.program->link();
+ if (!requiredProgram.program->isValid()) {
+ QString error;
+ qWarning() << "Shader program failed to link,"
+#if defined(QT_DEBUG)
+ << '\n'
+ << " Shaders Used:" << '\n'
+ << " mainVertexShader = " << requiredProgram.mainVertexShader->objectName() << '\n'
+ << " positionVertexShader = " << requiredProgram.positionVertexShader->objectName() << '\n'
+ << " mainFragShader = " << requiredProgram.mainFragShader->objectName() << '\n'
+ << " srcPixelFragShader = " << requiredProgram.srcPixelFragShader->objectName() << '\n'
+ << " maskFragShader = " << requiredProgram.maskFragShader->objectName() << '\n'
+ << " compositionFragShader = "<< requiredProgram.compositionFragShader->objectName() << '\n'
+#endif
+ << " Error Log:" << '\n'
+ << " " << requiredProgram.program->errors();
+ qWarning() << error;
+ }
+ else {
+ cachedPrograms.append(requiredProgram);
+ currentShaderProg = requiredProgram.program;
+ currentShaderProg->enable();
+ }
+ shaderProgNeedsChanging = false;
+}
+
+void QGLEngineShaderManager::compileNamedShader(QGLEngineShaderManager::ShaderName name, QGLShader::ShaderType type)
+{
+ if (compiledShaders[name])
+ return;
+
+ QGLShader *newShader = new QGLShader(type, ctx, this);
+ newShader->setSourceCode(qglEngineShaderSourceCode[name]);
+ // newShader->compile(); ### does not exist?
+
+#if defined(QT_DEBUG)
+ // Name the shader for easier debugging
+ QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("ShaderName"));
+ newShader->setObjectName(QLatin1String(m.valueToKey(name)));
+#endif
+
+ compiledShaders[name] = newShader;
+}
+
+
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
new file mode 100644
index 0000000..dec8f56
--- /dev/null
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+/*
+ VERTEX SHADERS
+ ==============
+
+ Vertex shaders are specified as multiple (partial) shaders. On desktop,
+ this works fine. On ES, QGLShader & QGLShaderProgram will make partial
+ shaders work by concatenating the source in each QGLShader and compiling
+ it as a single shader. This is abstracted nicely by QGLShaderProgram and
+ the GL2 engine doesn't need to worry about it.
+
+ Generally, there's two vertex shader objects. The position shaders are
+ the ones which set gl_Position. There's also two "main" vertex shaders,
+ one which just calls the position shader and another which also passes
+ through some texture coordinates from a vertex attribute array to a
+ varying. These texture coordinates are used for mask position in text
+ rendering and for the source coordinates in drawImage/drawPixmap. There's
+ also a "Simple" vertex shader for rendering a solid colour (used to render
+ into the stencil buffer where the actual colour value is discarded).
+
+ The position shaders for brushes look scary. This is because many of the
+ calculations which logically belong in the fragment shader have been moved
+ into the vertex shader to improve performance. This is why the position
+ calculation is in a seperate shader. Not only does it calculate the
+ position, but it also calculates some data to be passed to the fragment
+ shader as a varying. It is optimal to move as much of the calculation as
+ possible into the vertex shader as this is executed less often.
+
+ The varyings passed to the fragment shaders are interpolated (which is
+ cheap). Unfortunately, GL will apply perspective correction to the
+ interpolation calusing errors. To get around this, the vertex shader must
+ apply perspective correction itself and set the w-value of gl_Position to
+ zero. That way, GL will be tricked into thinking it doesn't need to apply a
+ perspective correction and use linear interpolation instead (which is what
+ we want). Of course, if the brush transform is affeine, no perspective
+ correction is needed and a simpler vertex shader can be used instead.
+
+ So there are the following "main" vertex shaders:
+ qglslMainVertexShader
+ qglslMainWithTexCoordsVertexShader
+
+ And the the following position vertex shaders:
+ qglslPositionOnlyVertexShader
+ qglslPositionWithTextureBrushVertexShader
+ qglslPositionWithPatternBrushVertexShader
+ qglslPositionWithLinearGradientBrushVertexShader
+ qglslPositionWithRadialGradientBrushVertexShader
+ qglslPositionWithConicalGradientBrushVertexShader
+ qglslAffinePositionWithTextureBrushVertexShader
+ qglslAffinePositionWithPatternBrushVertexShader
+ qglslAffinePositionWithLinearGradientBrushVertexShader
+ qglslAffinePositionWithRadialGradientBrushVertexShader
+ qglslAffinePositionWithConicalGradientBrushVertexShader
+
+ Leading to 23 possible vertex shaders
+
+
+ FRAGMENT SHADERS
+ ================
+
+ Fragment shaders are also specified as multiple (partial) shaders. The
+ different fragment shaders represent the different stages in Qt's fragment
+ pipeline. There are 1-3 stages in this pipeline: First stage is to get the
+ fragment's colour value. The next stage is to get the fragment's mask value
+ (coverage value for anti-aliasing) and the final stage is to blend the
+ incoming fragment with the background (for composition modes not supported
+ by GL).
+
+ Of these, the first stage will always be present. If Qt doesn't need to
+ apply anti-aliasing (because it's off or handled by multisampling) then
+ the coverage value doesn't need to be applied. (Note: There are two types
+ of mask, one for regular anti-aliasing and one for sub-pixel anti-
+ aliasing.) If the composition mode is one which GL supports natively then
+ the blending stage doesn't need to be applied.
+
+ As eash stage can have multiple implementations, they are abstracted as
+ GLSL function calls with the following signatures:
+
+ Brushes & image drawing are implementations of "qcolorp vec4 srcPixel()":
+ qglslImageSrcFragShader
+ qglslNonPremultipliedImageSrcFragShader
+ qglslSolidBrushSrcFragShader
+ qglslTextureBrushSrcFragShader
+ qglslPatternBrushSrcFragShader
+ qglslLinearGradientBrushSrcFragShader
+ qglslRadialGradientBrushSrcFragShader
+ qglslConicalGradientBrushSrcFragShader
+ NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied
+
+ Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)":
+ qglslMaskFragmentShader
+ qglslRgbMaskFragmentShader
+ qglslRgbMaskWithGammaFragmentShader
+
+ Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)":
+ qglslColorBurnCompositionModeFragmentShader
+ qglslColorDodgeCompositionModeFragmentShader
+ qglslDarkenCompositionModeFragmentShader
+ qglslDifferenceCompositionModeFragmentShader
+ qglslExclusionCompositionModeFragmentShader
+ qglslHardLightCompositionModeFragmentShader
+ qglslLightenCompositionModeFragmentShader
+ qglslMultiplyCompositionModeFragmentShader
+ qglslOverlayCompositionModeFragmentShader
+ qglslScreenCompositionModeFragmentShader
+ qglslSoftLightCompositionModeFragmentShader
+
+
+ Note: In the future, some GLSL compilers will support an extension allowing
+ a new 'color' precision specifier. To support this, qcolorp is used for
+ all color components so it can be defined to colorp or lowp depending upon
+ the implementation.
+
+ So there are differnt frament shader main functions, depending on the
+ number & type of pipelines the fragment needs to go through.
+
+ The choice of which main() fragment shader string to use depends on:
+ - Use of global opacity
+ - Brush style (some brushes apply opacity themselves)
+ - Use & type of mask (TODO: Need to support high quality anti-aliasing & text)
+ - Use of non-GL Composition mode
+
+ Leading to the following fragment shader main functions:
+ gl_FragColor = compose(applyMask(srcPixel()*globalOpacity));
+ gl_FragColor = compose(applyMask(srcPixel()));
+ gl_FragColor = applyMask(srcPixel()*globalOpacity);
+ gl_FragColor = applyMask(srcPixel());
+ gl_FragColor = compose(srcPixel()*globalOpacity);
+ gl_FragColor = compose(srcPixel());
+ gl_FragColor = srcPixel()*globalOpacity;
+ gl_FragColor = srcPixel();
+
+ Called:
+ qglslMainFragmentShader_CMO
+ qglslMainFragmentShader_CM
+ qglslMainFragmentShader_MO
+ qglslMainFragmentShader_M
+ qglslMainFragmentShader_CO
+ qglslMainFragmentShader_C
+ qglslMainFragmentShader_O
+ qglslMainFragmentShader
+
+ Where:
+ M = Mask
+ C = Composition
+ O = Global Opacity
+
+
+ CUSTOM SHADER CODE (idea, depricated)
+ ==================
+
+ The use of custom shader code is supported by the engine for drawImage and
+ drawPixmap calls. This is implemented via hooks in the fragment pipeline.
+ The custom shader is passed to the engine as a partial fragment shader
+ (QGLCustomizedShader). The shader will implement a pre-defined method name
+ which Qt's fragment pipeline will call. There are two different hooks which
+ can be implemented as custom shader code:
+
+ mediump vec4 customShader(sampler2d src, vec2 srcCoords)
+ mediump vec4 customShaderWithDest(sampler2d dest, sampler2d src, vec2 srcCoords)
+
+*/
+
+#ifndef QGLENGINE_SHADER_MANAGER_H
+#define QGLENGINE_SHADER_MANAGER_H
+
+#include <QGLShader>
+#include <QGLShaderProgram>
+#include <QPainter>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+
+struct QGLEngineShaderProg
+{
+ QGLShader* mainVertexShader;
+ QGLShader* positionVertexShader;
+ QGLShader* mainFragShader;
+ QGLShader* srcPixelFragShader;
+ QGLShader* maskFragShader; // Can be null for no mask
+ QGLShader* compositionFragShader; // Can be null for GL-handled mode
+ QGLShaderProgram* program;
+};
+
+/*
+struct QGLEngineCachedShaderProg
+{
+ QGLEngineCachedShaderProg(QGLEngineShaderManager::ShaderName vertexMain,
+ QGLEngineShaderManager::ShaderName vertexPosition,
+ QGLEngineShaderManager::ShaderName fragMain,
+ QGLEngineShaderManager::ShaderName pixelSrc,
+ QGLEngineShaderManager::ShaderName mask,
+ QGLEngineShaderManager::ShaderName composition);
+
+ int cacheKey;
+ QGLShaderProgram* program;
+}
+*/
+
+static const GLuint QT_VERTEX_COORDS_ATTR = 0;
+static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
+
+class QGLEngineShaderManager : public QObject
+{
+ Q_OBJECT;
+public:
+ QGLEngineShaderManager(QGLContext* context);
+ ~QGLEngineShaderManager();
+
+ enum MaskType {NoMask, PixelMask, SubPixelMask, SubPixelWithGammaMask};
+ enum PixelSrcType {
+ ImageSrc = Qt::TexturePattern+1,
+ NonPremultipliedImageSrc = Qt::TexturePattern+2
+ };
+
+ // There are optimisations we can do, depending on the brush transform:
+ // 1) May not have to apply perspective-correction
+ // 2) Can use lower precision for matrix
+ void optimiseForBrushTransform(const QTransform transform);
+ void setSrcPixelType(Qt::BrushStyle);
+ void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
+ void setTextureCoordsEnabled(bool); // For images & text glyphs
+ void setUseGlobalOpacity(bool);
+ void setMaskType(MaskType);
+ void setCompositionMode(QPainter::CompositionMode);
+
+ bool shaderProgramDirty(); // returns true if the shader program needs to be changed
+ void useCorrectShaderProg();
+
+ QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
+ QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
+
+ enum ShaderName {
+ MainVertexShader,
+ MainWithTexCoordsVertexShader,
+
+ PositionOnlyVertexShader,
+ PositionWithPatternBrushVertexShader,
+ PositionWithLinearGradientBrushVertexShader,
+ PositionWithConicalGradientBrushVertexShader,
+ PositionWithRadialGradientBrushVertexShader,
+ PositionWithTextureBrushVertexShader,
+ AffinePositionWithPatternBrushVertexShader,
+ AffinePositionWithLinearGradientBrushVertexShader,
+ AffinePositionWithConicalGradientBrushVertexShader,
+ AffinePositionWithRadialGradientBrushVertexShader,
+ AffinePositionWithTextureBrushVertexShader,
+
+ MainFragmentShader_CMO,
+ MainFragmentShader_CM,
+ MainFragmentShader_MO,
+ MainFragmentShader_M,
+ MainFragmentShader_CO,
+ MainFragmentShader_C,
+ MainFragmentShader_O,
+ MainFragmentShader,
+
+ ImageSrcFragmentShader,
+ NonPremultipliedImageSrcFragmentShader,
+ SolidBrushSrcFragmentShader,
+ TextureBrushSrcFragmentShader,
+ PatternBrushSrcFragmentShader,
+ LinearGradientBrushSrcFragmentShader,
+ RadialGradientBrushSrcFragmentShader,
+ ConicalGradientBrushSrcFragmentShader,
+ ShockingPinkSrcFragmentShader,
+
+ MaskFragmentShader,
+ RgbMaskFragmentShader,
+ RgbMaskWithGammaFragmentShader,
+
+ MultiplyCompositionModeFragmentShader,
+ ScreenCompositionModeFragmentShader,
+ OverlayCompositionModeFragmentShader,
+ DarkenCompositionModeFragmentShader,
+ LightenCompositionModeFragmentShader,
+ ColorDodgeCompositionModeFragmentShader,
+ ColorBurnCompositionModeFragmentShader,
+ HardLightCompositionModeFragmentShader,
+ SoftLightCompositionModeFragmentShader,
+ DifferenceCompositionModeFragmentShader,
+ ExclusionCompositionModeFragmentShader,
+
+ TotalShaderCount, InvalidShaderName
+ };
+
+/*
+ // These allow the ShaderName enum to be used as a cache key
+ const int mainVertexOffset = 0;
+ const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader;
+ const int mainFragOffset = (1<<6) - MainFragmentShader_CMO;
+ const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader;
+ const int maskOffset = (1<<14) - NoMaskShader;
+ const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader;
+*/
+
+#if defined (QT_DEBUG)
+ Q_ENUMS(ShaderName);
+#else
+#error Release build not supported yet
+#endif
+
+
+private:
+ QGLContext* ctx;
+ bool shaderProgNeedsChanging;
+
+ // Current state variables which influence the choice of shader:
+ QTransform brushTransform;
+ int srcPixelType;
+ bool useGlobalOpacity;
+ MaskType maskType;
+ bool useTextureCoords;
+ QPainter::CompositionMode compositionMode;
+
+ QGLShaderProgram* simpleShaderProg;
+ QGLShaderProgram* currentShaderProg;
+
+ // TODO: Possibly convert to a LUT
+ QList<QGLEngineShaderProg> cachedPrograms;
+
+ QGLShader* compiledShaders[TotalShaderCount];
+
+ void compileNamedShader(QGLEngineShaderManager::ShaderName name, QGLShader::ShaderType type);
+
+ static const char* qglEngineShaderSourceCode[TotalShaderCount];
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QGLENGINE_SHADER_MANAGER_H
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
new file mode 100644
index 0000000..f2facac
--- /dev/null
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef QGL_ENGINE_SHADER_SOURCE_H
+#define QGL_ENGINE_SHADER_SOURCE_H
+
+#include "qglengineshadermanager_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+
+static const char* const qglslMainVertexShader = "\
+ void setPosition();\
+ void main(void)\
+ {\
+ setPosition();\
+ }";
+
+static const char* const qglslMainWithTexCoordsVertexShader = "\
+ attribute lowp vec2 textureCoordArray; \
+ varying lowp vec2 textureCoords; \
+ void setPosition();\
+ void main(void) \
+ {\
+ setPosition();\
+ textureCoords = textureCoordArray; \
+ }";
+
+
+static const char* const qglslPositionOnlyVertexShader = "\
+ attribute highp vec4 vertexCoordsArray;\
+ uniform highp mat4 pmvMatrix;\
+ void setPosition(void)\
+ {\
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ }";
+
+
+// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
+static const char* const qglslPositionWithPatternBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray; \
+ uniform highp mat4 pmvMatrix; \
+ uniform mediump vec2 halfViewportSize; \
+ uniform mediump vec2 invertedTextureSize; \
+ uniform mediump mat3 brushTransform; \
+ varying mediump vec2 patternTexCoords; \
+ void setPosition(void) { \
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \
+ patternTexCoords.y = -patternTexCoords.y; \
+ }";
+
+static const char* const qglslAffinePositionWithPatternBrushVertexShader
+ = qglslPositionWithPatternBrushVertexShader;
+
+static const char* const qglslPatternBrushSrcFragmentShader = "\
+ uniform sampler2D brushTexture;\
+ uniform lowp vec4 patternColor; \
+ varying mediump vec2 patternTexCoords;\
+ lowp vec4 srcPixel() { \
+ return patternColor * texture2D(brushTexture, patternTexCoords).r; \
+ }\n";
+
+
+// Linear Gradient Brush
+static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray; \
+ uniform highp mat4 pmvMatrix; \
+ uniform mediump vec2 halfViewportSize; \
+ uniform highp vec3 linearData; \
+ uniform highp mat3 brushTransform; \
+ varying mediump float index ; \
+ void setPosition() { \
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \
+ }";
+
+static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader
+ = qglslPositionWithLinearGradientBrushVertexShader;
+
+static const char* const qglslLinearGradientBrushSrcFragmentShader = "\
+ uniform sampler2D brushTexture; \
+ varying mediump float index; \
+ lowp vec4 srcPixel() { \
+ mediump vec2 val = vec2(index, 0.5); \
+ return texture2D(brushTexture, val); \
+ }\n";
+
+
+// Conical Gradient Brush
+static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray;\
+ uniform highp mat4 pmvMatrix;\
+ uniform mediump vec2 halfViewportSize; \
+ uniform highp mat3 brushTransform; \
+ varying highp vec2 A; \
+ void setPosition(void)\
+ {\
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ A = hTexCoords.xy * invertedHTexCoordsZ; \
+ }";
+
+static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader
+ = qglslPositionWithConicalGradientBrushVertexShader;
+
+static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\
+ #define INVERSE_2PI 0.1591549430918953358 \n\
+ uniform sampler2D brushTexture; \n\
+ uniform mediump float angle; \
+ varying highp vec2 A; \
+ lowp vec4 srcPixel() { \
+ highp float t; \
+ if (abs(A.y) == abs(A.x)) \
+ t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \
+ else \
+ t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \
+ return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \
+ }";
+
+
+// Radial Gradient Brush
+static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray;\
+ uniform highp mat4 pmvMatrix;\
+ uniform mediump vec2 halfViewportSize; \
+ uniform highp mat3 brushTransform; \
+ uniform highp vec2 fmp; \
+ varying highp float b; \
+ varying highp vec2 A; \
+ void setPosition(void) \
+ {\
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ A = hTexCoords.xy * invertedHTexCoordsZ; \
+ b = 2.0 * dot(A, fmp); \
+ }";
+
+static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader
+ = qglslPositionWithRadialGradientBrushVertexShader;
+
+static const char* const qglslRadialGradientBrushSrcFragmentShader = "\
+ uniform sampler2D brushTexture; \
+ uniform highp float fmp2_m_radius2; \
+ uniform highp float inverse_2_fmp2_m_radius2; \
+ varying highp float b; \
+ varying highp vec2 A; \
+ lowp vec4 srcPixel() { \
+ highp float c = -dot(A, A); \
+ highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \
+ return texture2D(brushTexture, val); \
+ }";
+
+
+// Texture Brush
+static const char* const qglslPositionWithTextureBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray; \
+ uniform highp mat4 pmvMatrix; \
+ uniform mediump vec2 halfViewportSize; \
+ uniform mediump vec2 invertedTextureSize; \
+ uniform mediump mat3 brushTransform; \
+ varying mediump vec2 brushTextureCoords; \
+ void setPosition(void) { \
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \
+ brushTextureCoords.y = -brushTextureCoords.y; \
+ }";
+
+static const char* const qglslAffinePositionWithTextureBrushVertexShader
+ = qglslPositionWithTextureBrushVertexShader;
+
+static const char* const qglslTextureBrushSrcFragmentShader = "\
+ varying mediump vec2 brushTextureCoords; \
+ uniform sampler2D brushTexture; \
+ lowp vec4 srcPixel() { \
+ return texture2D(brushTexture, brushTextureCoords); \
+ }";
+
+
+// Solid Fill Brush
+static const char* const qglslSolidBrushSrcFragmentShader = "\
+ uniform lowp vec4 fragmentColor; \
+ lowp vec4 srcPixel() { \
+ return fragmentColor; \
+ }";
+
+static const char* const qglslImageSrcFragmentShader = "\
+ varying highp vec2 textureCoords; \
+ uniform sampler2D imageTexture; \
+ lowp vec4 srcPixel() { \
+ return texture2D(imageTexture, textureCoords); \
+ }";
+
+static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\
+ varying highp vec2 textureCoords; \
+ uniform sampler2D imageTexture; \
+ lowp vec4 srcPixel() { \
+ lowp vec4 sample = texture2D(imageTexture, textureCoords); \
+ sample.rgb = sample.rgb * sample.a; \
+ return sample; \
+ }";
+
+static const char* const qglslShockingPinkSrcFragmentShader = "\
+ lowp vec4 srcPixel() { \
+ return lowp vec4(0.98, 0.06, 0.75, 1.0); \
+ }";
+
+
+static const char* const qglslMainFragmentShader_CMO = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = compose(applyMask(srcPixel()*globalOpacity)); \
+ }";
+
+static const char* const qglslMainFragmentShader_CM = "\
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = compose(applyMask(srcPixel())); \
+ }";
+
+static const char* const qglslMainFragmentShader_MO = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ void main() { \
+ gl_FragColor = applyMask(srcPixel()*globalOpacity); \
+ }";
+
+static const char* const qglslMainFragmentShader_M = "\
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ void main() { \
+ gl_FragColor = applyMask(srcPixel()); \
+ }";
+
+static const char* const qglslMainFragmentShader_CO = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = compose(srcPixel()*globalOpacity); \
+ }";
+
+static const char* const qglslMainFragmentShader_C = "\
+ lowp vec4 srcPixel(); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = compose(srcPixel()); \
+ }";
+
+static const char* const qglslMainFragmentShader_O = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ void main() { \
+ gl_FragColor = srcPixel()*globalOpacity; \
+ }";
+
+static const char* const qglslMainFragmentShader = "\
+ lowp vec4 srcPixel(); \
+ void main() { \
+ gl_FragColor = srcPixel(); \
+ }";
+
+static const char* const qglslMaskFragmentShader = "\
+ varying highp vec2 textureCoords;\
+ uniform sampler2D maskTexture;\
+ lowp vec4 applyMask(lowp vec4 src) \
+ {\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \
+ return src * mask.r; \
+ }";
+
+/*
+ Left to implement:
+ RgbMaskFragmentShader,
+ RgbMaskWithGammaFragmentShader,
+
+ MultiplyCompositionModeFragmentShader,
+ ScreenCompositionModeFragmentShader,
+ OverlayCompositionModeFragmentShader,
+ DarkenCompositionModeFragmentShader,
+ LightenCompositionModeFragmentShader,
+ ColorDodgeCompositionModeFragmentShader,
+ ColorBurnCompositionModeFragmentShader,
+ HardLightCompositionModeFragmentShader,
+ SoftLightCompositionModeFragmentShader,
+ DifferenceCompositionModeFragmentShader,
+ ExclusionCompositionModeFragmentShader,
+*/
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // GLGC_SHADER_SOURCE_H
diff --git a/src/opengl/gl2paintengineex/qglpexshadermanager.cpp b/src/opengl/gl2paintengineex/qglpexshadermanager.cpp
deleted file mode 100644
index e460e08..0000000
--- a/src/opengl/gl2paintengineex/qglpexshadermanager.cpp
+++ /dev/null
@@ -1,450 +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 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 "qglpexshadermanager_p.h"
-
-#include "glgc_shader_source.h"
-
-QGLPEXShaderManager::QGLPEXShaderManager(const QGLContext* context)
-{
- ctx = const_cast<QGLContext*>(context);
-
- defaultVertexShader= new QGLShader(QGLShader::VertexShader, context);
- defaultVertexShader->addSource(QLatin1String(qglslDefaultVertexShader));
- if (!defaultVertexShader->compile())
- qWarning() << "Default vertex shader failed to compile: " << defaultVertexShader->log();
-
- noBrushShader = new QGLShader(QGLShader::FragmentShader, context);
- noBrushShader->addSource(QLatin1String(qglslFragmentShaderMain));
- noBrushShader->addSource(QLatin1String(qglslNoBrushFragmentShader));
- if (!noBrushShader->compile())
- qWarning() << "No brush shader failed to compile:" << noBrushShader->log();
-
-
- // Create a program for noBrush:
- QGLShaderProgram* noBrushProg = new QGLShaderProgram(ctx);
- noBrushProg->addShader(defaultVertexShader);
- noBrushProg->addShader(noBrushShader);
- if (!noBrushProg->link())
- qWarning() << "NoBrush shader program failed to link:" << noBrushProg->log();
-
- // Add noBrush Program to cache:
- QGLCachedShaderProg cachedProg;
- cachedProg.vertexShader = defaultVertexShader;
- cachedProg.brushShader = noBrushShader;
- cachedProg.compositionShader = 0;
- cachedProg.shader = noBrushProg;
- cachedPrograms.append(cachedProg);
-
-
- // Set state
- useGlobalOpacity = true;
- currentBrushStyle = Qt::NoBrush;
- currentTransformType = FullTransform;
- shaderProgNeedsChanging = false;
- activeProgram = noBrushProg;
-
- solidBrushShader = 0;
-
- conicalBrushVertexShader = 0;
- conicalBrushFragmentShader = 0;
-
- radialBrushVertexShader = 0;
- radialBrushFragmentShader = 0;
-
- linearBrushVertexShader = 0;
- linearBrushFragmentShader = 0;
-
- patternBrushVertexShader = 0;
- patternBrushFragmentShader = 0;
-
- textureBrushFragmentShader = 0;
- textureBrushVertexShader = 0;
-
- simpleFragmentShader = 0;
- simpleShaderProgram = 0;
-
- imageVertexShader = 0;
- imageFragmentShader = 0;
- imageShaderProgram = 0;
-
- textVertexShader = 0;
- textFragmentShader = 0;
- textShaderProgram = 0;
-}
-
-QGLPEXShaderManager::~QGLPEXShaderManager()
-{
- delete defaultVertexShader;
- delete imageVertexShader;
- delete imageFragmentShader;
- delete imageShaderProgram;
- delete textVertexShader;
- delete textFragmentShader;
- delete textShaderProgram;
- delete noBrushShader;
- delete solidBrushShader;
-
- delete conicalBrushVertexShader;
- delete conicalBrushFragmentShader;
-
- delete radialBrushVertexShader;
- delete radialBrushFragmentShader;
-
- delete linearBrushFragmentShader;
- delete linearBrushVertexShader;
-
- delete patternBrushFragmentShader;
- delete patternBrushVertexShader;
-
- delete textureBrushFragmentShader;
- delete textureBrushVertexShader;
-
- delete simpleFragmentShader;
- delete simpleShaderProgram;
-}
-
-void QGLPEXShaderManager::setUseGlobalOpacity(bool value)
-{
- if (value != useGlobalOpacity)
- shaderProgNeedsChanging = true;
-
- useGlobalOpacity = value;
-}
-
-void QGLPEXShaderManager::setBrushStyle(Qt::BrushStyle style)
-{
- if (currentBrushStyle != style)
- shaderProgNeedsChanging = true;
-
- currentBrushStyle = style;
-}
-
-void QGLPEXShaderManager::setAffineOnlyBrushTransform(bool value)
-{
- Q_UNUSED(value);
- // TODO
-}
-
-bool QGLPEXShaderManager::useCorrectShaderProg()
-{
- if (!shaderProgNeedsChanging) {
- activeProgram->use();
- return false;
- }
-
- const char* fragmentShaderMainSrc = qglslFragmentShaderMain;
- QGLShader* vertexShader = defaultVertexShader;
- QGLShader* fragmentShader = noBrushShader;
-
- // Make sure we compile up the correct brush shader
- switch (currentBrushStyle) {
- case Qt::NoBrush:
- break;
- case Qt::SolidPattern:
- if (!solidBrushShader) {
- qDebug("Compiling qglslSolidBrushFragmentShader");
- solidBrushShader = new QGLShader(QGLShader::FragmentShader, ctx);
- solidBrushShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain));
- solidBrushShader->addSource(QLatin1String(qglslSolidBrushFragmentShader));
- if (!solidBrushShader->compile())
- qWarning() << "qglslSolidBrush failed to compile:" << solidBrushShader->log();
- }
- fragmentShader = solidBrushShader;
- break;
- case Qt::TexturePattern:
- if (!textureBrushVertexShader) {
- qDebug("Compiling qglslTextureBrushVertexShader");
- textureBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- textureBrushVertexShader->addSource(QLatin1String(qglslTextureBrushVertexShader));
- if (!textureBrushVertexShader->compile()) {
- qWarning() << "qglslTextureBrushVertexShader failed to compile: "
- << textureBrushVertexShader->log();
- }
- }
- vertexShader = textureBrushVertexShader;
-
- if (!textureBrushFragmentShader) {
- qDebug("Compiling qglslTextureBrushFragmentShader");
- textureBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- textureBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- textureBrushFragmentShader->addSource(QLatin1String(qglslTextureBrushFragmentShader));
- if (!textureBrushFragmentShader->compile()) {
- qWarning() << "qglslTextureBrushFragmentShader failed to compile:"
- << textureBrushFragmentShader->log();
- }
- }
- fragmentShader = textureBrushFragmentShader;
- break;
- case Qt::LinearGradientPattern:
- if (!linearBrushVertexShader) {
- qDebug("Compiling qglslLinearGradientBrushVertexShader");
- linearBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- linearBrushVertexShader->addSource(QLatin1String(qglslLinearGradientBrushVertexShader));
- if (!linearBrushVertexShader->compile()) {
- qWarning() << "qglslLinearGradientBrushVertexShader failed to compile: "
- << linearBrushVertexShader->log();
- }
- }
- vertexShader = linearBrushVertexShader;
-
- if (!linearBrushFragmentShader) {
- qDebug("Compiling qglslLinearGradientBrushFragmentShader");
- linearBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- linearBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- linearBrushFragmentShader->addSource(QLatin1String(qglslLinearGradientBrushFragmentShader));
- if (!linearBrushFragmentShader->compile()) {
- qWarning() << "qglslLinearGradientBrushFragmentShader failed to compile:"
- << linearBrushFragmentShader->log();
- }
- }
- fragmentShader = linearBrushFragmentShader;
- break;
- case Qt::RadialGradientPattern:
- if (!radialBrushVertexShader) {
- qDebug("Compiling qglslRadialGradientBrushVertexShader");
- radialBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- radialBrushVertexShader->addSource(QLatin1String(qglslRadialGradientBrushVertexShader));
- if (!radialBrushVertexShader->compile()) {
- qWarning() << "qglslRadialGradientBrushVertexShader failed to compile: "
- << radialBrushVertexShader->log();
- }
- }
- vertexShader = radialBrushVertexShader;
-
- if (!radialBrushFragmentShader) {
- qDebug("Compiling qglslRadialGradientBrushFragmentShader");
- radialBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- radialBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- radialBrushFragmentShader->addSource(QLatin1String(qglslRadialGradientBrushFragmentShader));
- if (!radialBrushFragmentShader->compile()) {
- qWarning() << "qglslRadialGradientBrushFragmentShader failed to compile:"
- << radialBrushFragmentShader->log();
- }
- }
- fragmentShader = radialBrushFragmentShader;
- break;
- case Qt::ConicalGradientPattern:
- // FIXME: We currently use the same vertex shader as radial brush
- if (!conicalBrushVertexShader) {
- qDebug("Compiling qglslConicalGradientBrushVertexShader");
- conicalBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- conicalBrushVertexShader->addSource(QLatin1String(qglslConicalGradientBrushVertexShader));
- if (!conicalBrushVertexShader->compile()) {
- qWarning() << "qglslConicalGradientBrushVertexShader failed to compile: "
- << conicalBrushVertexShader->log();
- }
- }
- vertexShader = conicalBrushVertexShader;
-
- if (!conicalBrushFragmentShader) {
- qDebug("Compiling qglslConicalGradientBrushFragmentShader");
- conicalBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- conicalBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- conicalBrushFragmentShader->addSource(QLatin1String(qglslConicalGradientBrushFragmentShader));
- if (!conicalBrushFragmentShader->compile()) {
- qWarning() << "qglslConicalGradientBrushFragmentShader failed to compile:"
- << conicalBrushFragmentShader->log();
- }
- }
- fragmentShader = conicalBrushFragmentShader;
- break;
- case Qt::Dense1Pattern:
- case Qt::Dense2Pattern:
- case Qt::Dense3Pattern:
- case Qt::Dense4Pattern:
- case Qt::Dense5Pattern:
- case Qt::Dense6Pattern:
- case Qt::Dense7Pattern:
- case Qt::HorPattern:
- case Qt::VerPattern:
- case Qt::CrossPattern:
- case Qt::BDiagPattern:
- case Qt::FDiagPattern:
- case Qt::DiagCrossPattern:
- if (!patternBrushVertexShader) {
- qDebug("Compiling qglslPatternBrushVertexShader");
- patternBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- patternBrushVertexShader->addSource(QLatin1String(qglslPatternBrushVertexShader));
- if (!patternBrushVertexShader->compile()) {
- qWarning() << "qglslPatternBrushVertexShader failed to compile: "
- << patternBrushVertexShader->log();
- }
- }
- vertexShader = patternBrushVertexShader;
-
- if (!patternBrushFragmentShader) {
- qDebug("Compiling qglslPatternBrushFragmentShader");
- patternBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- patternBrushFragmentShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain));
- patternBrushFragmentShader->addSource(QLatin1String(qglslPatternBrushFragmentShader));
- if (!patternBrushFragmentShader->compile()) {
- qWarning() << "qglslPatternBrushFragmentShader failed to compile:"
- << patternBrushFragmentShader->log();
- }
- }
- fragmentShader = patternBrushFragmentShader;
- break;
- default:
- qWarning("Unimplemented brush style (%d)", currentBrushStyle);
- }
-
- // Now newBrushShader is set correctly, check to see if we already have the program
- // already linked and ready to go in the cache:
- bool foundProgram = false;
- foreach (QGLCachedShaderProg cachedProg, cachedPrograms) {
- if ((cachedProg.vertexShader == vertexShader) &&
- (cachedProg.brushShader == fragmentShader) &&
- (cachedProg.compositionShader == 0) ) {
-
- activeProgram = cachedProg.shader;
- foundProgram = true;
- break;
- }
- }
-
- if (!foundProgram) {
- qDebug() << "Linking shader program for " << currentBrushStyle;
- // Required program not found - create it.
- QGLShaderProgram* newProg = new QGLShaderProgram(ctx);
-
- newProg->addShader(vertexShader);
- newProg->addShader(fragmentShader);
-
- if (!newProg->link())
- qWarning() << "Shader program for " << currentBrushStyle << "failed to link:" << newProg->log();
-
- QGLCachedShaderProg cachedProg;
- cachedProg.vertexShader = vertexShader;
- cachedProg.brushShader = fragmentShader;
- cachedProg.compositionShader = 0;
- cachedProg.shader = newProg;
-
- cachedPrograms.append(cachedProg);
- activeProgram = newProg;
- }
-
- activeProgram->use();
- shaderProgNeedsChanging = false;
- return true;
-}
-
-QGLShaderProgram* QGLPEXShaderManager::brushShader()
-{
- return activeProgram;
-}
-
-// The only uniform the simple shader has is the PMV matrix
-QGLShaderProgram* QGLPEXShaderManager::simpleShader()
-{
- if (!simpleShaderProgram) {
- simpleShaderProgram = new QGLShaderProgram(ctx);
-
- if (!simpleFragmentShader) {
- simpleFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- simpleFragmentShader->addSource(QLatin1String(qglslSimpleFragmentShader));
- if (!simpleFragmentShader->compile())
- qWarning() << "qglslSimpleFragmentShader failed to compile:" << simpleFragmentShader->log();
- }
-
- simpleShaderProgram->addShader(defaultVertexShader);
- simpleShaderProgram->addShader(simpleFragmentShader);
- if (!simpleShaderProgram->link())
- qWarning() << "Simple shader program failed to link:" << simpleShaderProgram->log();
- }
-
- return simpleShaderProgram;
-}
-
-QGLShaderProgram* QGLPEXShaderManager::imageShader()
-{
- if (!imageShaderProgram) {
- if (!imageVertexShader) {
- imageVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- imageVertexShader->addSource(QLatin1String(qglslImageVertexShader));
- if (!imageVertexShader->compile())
- qWarning() << "Image/Pixmap vertex shader failed to compile:" << imageVertexShader->log();
- }
-
- if (!imageFragmentShader) {
- imageFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- imageFragmentShader->addSource(QLatin1String(qglslImageFragmentShader));
- if (!imageFragmentShader->compile())
- qWarning() << "Image/Pixmap fragment shader failed to compile:" << imageFragmentShader->log();
- }
-
- imageShaderProgram = new QGLShaderProgram(ctx);
- imageShaderProgram->addShader(imageVertexShader);
- imageShaderProgram->addShader(imageFragmentShader);
- if (!imageShaderProgram->link())
- qWarning() << "Image/Pixmap shader program failed to link:" << imageShaderProgram->log();
- }
-
- return imageShaderProgram;
-}
-
-QGLShaderProgram* QGLPEXShaderManager::textShader()
-{
- if (!textShaderProgram) {
- if (!textVertexShader) {
- textVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- textVertexShader->addSource(QLatin1String(qglslImageVertexShader));
- if (!textVertexShader->compile())
- qWarning() << "Text vertex shader failed to compile:" << textVertexShader->log();
- }
-
- if (!textFragmentShader) {
- textFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- textFragmentShader->addSource(QLatin1String(qglslTextFragmentShader));
- if (!textFragmentShader->compile())
- qWarning() << "Text fragment shader failed to compile:" << textFragmentShader->log();
- }
-
- textShaderProgram = new QGLShaderProgram(ctx);
- textShaderProgram->addShader(textVertexShader);
- textShaderProgram->addShader(textFragmentShader);
- if (!textShaderProgram->link())
- qWarning() << "Text shader program failed to link:" << textShaderProgram->log();
- }
-
- return textShaderProgram;
-}
-
diff --git a/src/opengl/gl2paintengineex/qglpexshadermanager_p.h b/src/opengl/gl2paintengineex/qglpexshadermanager_p.h
deleted file mode 100644
index c8f47b2..0000000
--- a/src/opengl/gl2paintengineex/qglpexshadermanager_p.h
+++ /dev/null
@@ -1,156 +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 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$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qglshader_p.h"
-
-
-// Worstcase combo: Brush->Mask->Composition
-
-/*
- Vertex shader source is specified with a single string. This string
- contains the main function and sets the gl_Position. The choice of
- which vertex shader to use depends on:
- - Brush style
- - Brush transform->isAffine()
-
- Fragment shaders are specified as multiple strings, one for the main
- function, one for the brush calculation and optionally one for the
- extended composition mode. Brushes are implementations of
- "mediump vec4 brush()"
- Composition modes are implemented as a
- "mediump vec4 compose(mediump vec4 color)"
- NOTE: Precision may change in future.
-
- The choice of which main() fragment shader string to use depends on:
- - Global opacity
- - Brush style (some brushes apply opacity themselves)
- - Use of mask (TODO: Need to support high quality anti-aliasing & text)
- - Composition mode
-
- The choice of which brush() fragment shader to use depends on:
- - Brush style
-
-*/
-
-
-struct QGLCachedShaderProg
-{
- QGLShader* vertexShader;
- QGLShader* brushShader;
- QGLShader* compositionShader;
- QGLShaderProgram* shader;
-};
-
-class QGLPEXShaderManager
-{
-public:
- QGLPEXShaderManager(const QGLContext* context);
- ~QGLPEXShaderManager();
-
- enum TransformType {IdentityTransform, ScaleTransform, TranslateTransform, FullTransform};
-
- void optimiseForBrushTransform(const QTransform& transform);
- void setBrushStyle(Qt::BrushStyle style);
- void setUseGlobalOpacity(bool value);
- void setAffineOnlyBrushTransform(bool value); // I.e. Do we need to apply perspective-correction?
- // Not doing so saves some vertex shader calculations.
-
- bool useCorrectShaderProg(); // returns true if the shader program has changed
-
- QGLShaderProgram* brushShader();
- QGLShaderProgram* simpleShader(); // Used to draw into e.g. stencil buffers
- QGLShaderProgram* imageShader();
- QGLShaderProgram* textShader();
-
-private:
- QGLShader* defaultVertexShader;
-
- QGLShader* imageVertexShader;
- QGLShader* imageFragmentShader;
- QGLShaderProgram* imageShaderProgram;
-
- QGLShader* textVertexShader;
- QGLShader* textFragmentShader;
- QGLShaderProgram* textShaderProgram;
-
- QGLShader* noBrushShader;
- QGLShader* solidBrushShader;
-
- QGLShader* conicalBrushVertexShader;
- QGLShader* conicalBrushFragmentShader;
-
- QGLShader* radialBrushVertexShader;
- QGLShader* radialBrushFragmentShader;
-
- QGLShader* linearBrushVertexShader;
- QGLShader* linearBrushFragmentShader;
-
- QGLShader* patternBrushVertexShader;
- QGLShader* patternBrushFragmentShader;
-
- QGLShader* textureBrushFragmentShader;
- QGLShader* textureBrushVertexShader;
-
- QGLShader* simpleFragmentShader;
- QGLShaderProgram* simpleShaderProgram;
-
- QGLShaderProgram* activeProgram;
-
- Qt::BrushStyle currentBrushStyle;
- bool useGlobalOpacity;
- TransformType currentTransformType;
- bool shaderProgNeedsChanging;
-
- QList<QGLCachedShaderProg> cachedPrograms;
-
- QGLContext* ctx;
-};
diff --git a/src/opengl/gl2paintengineex/qglshader.cpp b/src/opengl/gl2paintengineex/qglshader.cpp
index 4ac6e61..ea4cae9 100644
--- a/src/opengl/gl2paintengineex/qglshader.cpp
+++ b/src/opengl/gl2paintengineex/qglshader.cpp
@@ -51,6 +51,7 @@
#if !defined(QT_OPENGL_ES_2)
static const char *qglslDefines = "#define lowp\n#define mediump\n#define highp\n";
+#include "private/qgl_p.h"
#else
static const char *qglslDefines = "";
#endif
diff --git a/src/opengl/gl2paintengineex/qglshader_p.h b/src/opengl/gl2paintengineex/qglshader_p.h
index 4cbf3f6..64c9a42 100644
--- a/src/opengl/gl2paintengineex/qglshader_p.h
+++ b/src/opengl/gl2paintengineex/qglshader_p.h
@@ -81,7 +81,8 @@ SAMPLER_2D_SHADOW.
#include <QtOpenGL>
-#include <private/qgl_p.h>
+#define QGLShader QGLEngineShader
+#define QGLShaderProgram QGLEngineShaderProgram
typedef struct {
GLfloat a;
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index d0f0ad6..5a701aa 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -77,7 +77,7 @@
#include <private/qtextureglyphcache_p.h>
#include "qglgradientcache_p.h"
-#include "qglpexshadermanager_p.h"
+#include "qglengineshadermanager_p.h"
#include "qgl2pexvertexarray_p.h"
@@ -89,12 +89,13 @@ extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp
enum EngineMode {
ImageDrawingMode,
TextDrawingMode,
- DefaultMode
+ BrushDrawingMode
};
-static const GLuint QT_VERTEX_COORDS_ATTR = 0;
-static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
-static const GLuint QT_BRUSH_TEXTURE_UNIT = 0;
+static const GLuint QT_BRUSH_TEXTURE_UNIT = 0;
+static const GLuint QT_IMAGE_TEXTURE_UNIT = 0; //Can be the same as brush texture unit
+static const GLuint QT_MASK_TEXTURE_UNIT = 1;
+static const GLuint QT_BACKGROUND_TEXTURE_UNIT = 2;
class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
{
@@ -121,11 +122,11 @@ public:
void transferMode(EngineMode newMode);
- void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize);
- void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
-
+ // fill, drawOutline, drawTexture & drawCachedGlyphs are the rendering entry points:
void fill(const QVectorPath &path);
void drawOutline(const QVectorPath& path);
+ void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize);
+ void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
void drawVertexArrays(QGL2PEXVertexArray& vertexArray, GLenum primitive);
// ^ draws whatever is in the vertex array
@@ -135,7 +136,7 @@ public:
// ^ Calls drawVertexArrays to render into stencil buffer
void cleanStencilBuffer(const QGLRect& area);
- void prepareForDraw();
+ void prepareForDraw(bool srcPixelsAreOpaque);
inline void useSimpleShader();
inline QColor premultiplyColor(QColor c, GLfloat opacity);
@@ -153,9 +154,7 @@ public:
bool brushTextureDirty;
bool brushUniformsDirty;
bool simpleShaderMatrixUniformDirty;
- bool brushShaderMatrixUniformDirty;
- bool imageShaderMatrixUniformDirty;
- bool textShaderMatrixUniformDirty;
+ bool shaderMatrixUniformDirty;
bool stencilBuferDirty;
const QBrush* currentBrush; // May not be the state's brush!
@@ -170,7 +169,7 @@ public:
GLfloat pmvMatrix[4][4];
- QGLPEXShaderManager* shaderManager;
+ QGLEngineShaderManager* shaderManager;
// Clipping & state stuff stolen from QOpenGLPaintEngine:
void updateDepthClip();
@@ -192,7 +191,7 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform)
{
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+// glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit?
if (smoothPixmapTransform) {
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -221,21 +220,21 @@ void QGL2PaintEngineExPrivate::setBrush(const QBrush* brush)
currentBrush = brush;
brushTextureDirty = true;
brushUniformsDirty = true;
- shaderManager->setBrushStyle(currentBrush->style());
- shaderManager->setAffineOnlyBrushTransform(currentBrush->transform().isAffine());
+ shaderManager->setSrcPixelType(currentBrush->style());
+ shaderManager->optimiseForBrushTransform(currentBrush->transform());
}
// Unless this gets used elsewhere, it's probably best to merge it into fillStencilWithVertexArray
void QGL2PaintEngineExPrivate::useSimpleShader()
{
- shaderManager->simpleShader()->use();
+ shaderManager->simpleProgram()->enable();
if (matrixDirty)
updateMatrix();
if (simpleShaderMatrixUniformDirty) {
- shaderManager->simpleShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
+ shaderManager->simpleProgram()->setUniformValue("pmvMatrix", pmvMatrix);
simpleShaderMatrixUniformDirty = false;
}
}
@@ -252,7 +251,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
// Get the image data for the pattern
QImage texImage = qt_imageForBrush(style, true);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, true);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
}
@@ -272,12 +271,13 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
else
updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, true);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
glBindTexture(GL_TEXTURE_2D, texId);
}
else if (style == Qt::TexturePattern) {
const QPixmap& texPixmap = currentBrush->texture();
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, true);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
}
@@ -293,17 +293,11 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style == Qt::NoBrush)
return;
- GLfloat opacity = 1.0;
- if (q->state()->opacity < 0.99f)
- opacity = (GLfloat)q->state()->opacity;
- bool setOpacity = true;
-
QTransform brushQTransform = currentBrush->transform();
if (style == Qt::SolidPattern) {
- QColor col = premultiplyColor(currentBrush->color(), opacity);
- shaderManager->brushShader()->uniforms()[QLatin1String("fragmentColor")] = col;
- setOpacity = false;
+ QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
+ shaderManager->currentProgram()->setUniformValue("fragmentColor", col);
}
else {
// All other brushes have a transform and thus need the translation point:
@@ -312,13 +306,12 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style <= Qt::DiagCrossPattern) {
translationPoint = q->state()->brushOrigin;
- QColor col = premultiplyColor(currentBrush->color(), opacity);
+ QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
- shaderManager->brushShader()->uniforms()[QLatin1String("patternColor")] = col;
- setOpacity = false; //So code below doesn't try to set the opacity uniform
+ shaderManager->currentProgram()->setUniformValue("patternColor", col);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::LinearGradientPattern) {
const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient());
@@ -329,17 +322,16 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QPointF l = realFinal - realStart;
- // ###
- QGLVec3 linearData = {
+ QVector3D linearData(
l.x(),
l.y(),
1.0f / (l.x() * l.x() + l.y() * l.y())
- };
+ );
- shaderManager->brushShader()->uniforms()[QLatin1String("linearData")] = linearData;
+ shaderManager->currentProgram()->setUniformValue("linearData", linearData);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::ConicalGradientPattern) {
const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient());
@@ -347,10 +339,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0;
- shaderManager->brushShader()->uniforms()[QLatin1String("angle")] = angle;
+ shaderManager->currentProgram()->setUniformValue("angle", angle);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::RadialGradientPattern) {
const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient());
@@ -360,16 +352,15 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
translationPoint = realFocal;
QPointF fmp = realCenter - realFocal;
- shaderManager->brushShader()->uniforms()[QLatin1String("fmp")] = fmp;
+ shaderManager->currentProgram()->setUniformValue("fmp", fmp);
GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius;
- shaderManager->brushShader()->uniforms()[QLatin1String("fmp2_m_radius2")] = fmp2_m_radius2;
-
- shaderManager->brushShader()->uniforms()[QLatin1String("inverse_2_fmp2_m_radius2")] =
- GLfloat(1.0 / (2.0*fmp2_m_radius2));
+ shaderManager->currentProgram()->setUniformValue("fmp2_m_radius2", fmp2_m_radius2);
+ shaderManager->currentProgram()->setUniformValue("inverse_2_fmp2_m_radius2",
+ GLfloat(1.0 / (2.0*fmp2_m_radius2)));
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::TexturePattern) {
translationPoint = q->state()->brushOrigin;
@@ -377,10 +368,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
const QPixmap& texPixmap = currentBrush->texture();
QSizeF invertedTextureSize( 1.0 / texPixmap.width(), 1.0 / texPixmap.height() );
- shaderManager->brushShader()->uniforms()[QLatin1String("invertedTextureSize")] = invertedTextureSize;
+ shaderManager->currentProgram()->setUniformValue("invertedTextureSize", invertedTextureSize);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else
qWarning("QGL2PaintEngineEx: Unimplemented fill style");
@@ -389,11 +380,8 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QTransform gl_to_qt(1, 0, 0, -1, 0, height);
QTransform inv_matrix = gl_to_qt * (brushQTransform * q->state()->matrix).inverted() * translate;
- shaderManager->brushShader()->uniforms()[QLatin1String("brushTransform")] = inv_matrix;
- shaderManager->brushShader()->uniforms()[QLatin1String("brushTexture")] = QT_BRUSH_TEXTURE_UNIT;
-
- if (setOpacity)
- shaderManager->brushShader()->uniforms()[QLatin1String("opacity")] = opacity;
+ shaderManager->currentProgram()->setUniformValue("brushTransform", inv_matrix);
+ shaderManager->currentProgram()->setUniformValue("brushTexture", QT_BRUSH_TEXTURE_UNIT);
}
brushUniformsDirty = false;
}
@@ -456,9 +444,7 @@ void QGL2PaintEngineExPrivate::updateMatrix()
// The actual data has been updated so both shader program's uniforms need updating
simpleShaderMatrixUniformDirty = true;
- brushShaderMatrixUniformDirty = true;
- imageShaderMatrixUniformDirty = true;
- textShaderMatrixUniformDirty = true;
+ shaderMatrixUniformDirty = true;
}
@@ -529,22 +515,16 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect)
void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize)
{
-// qDebug("QGL2PaintEngineExPrivate::drawImage()");
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
+ transferMode(ImageDrawingMode);
- if (compositionModeDirty)
- updateCompositionMode();
-
- if (matrixDirty)
- updateMatrix();
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- if (imageShaderMatrixUniformDirty) {
- shaderManager->imageShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
- imageShaderMatrixUniformDirty = false;
- }
+ // Setup for texture drawing
+ shaderManager->setSrcPixelType(QGLEngineShaderManager::ImageSrc);
+ shaderManager->setTextureCoordsEnabled(true);
+ prepareForDraw(false); // ###
- if (q->state()->opacity < 0.99f)
- shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)q->state()->opacity;
+ shaderManager->currentProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
GLfloat dx = 1.0 / textureSize.width();
GLfloat dy = 1.0 / textureSize.height();
@@ -571,44 +551,35 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
matrixDirty = true;
if (newMode == TextDrawingMode) {
- glEnable(GL_BLEND);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
-
glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
- shaderManager->textShader()->use();
- shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
-
matrixDirty = true;
}
if (newMode == ImageDrawingMode) {
- // We have a shader specifically for drawPixmap/drawImage...
- shaderManager->imageShader()->use();
- shaderManager->imageShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
- shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)1.0;
-
glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticVertexCoordinateArray);
glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticTextureCoordinateArray);
-
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
}
+ // This needs to change when we implement high-quality anti-aliasing...
+ if (newMode != TextDrawingMode)
+ shaderManager->setMaskType(QGLEngineShaderManager::NoMask);
+
mode = newMode;
}
void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path)
{
- transferMode(DefaultMode);
+ transferMode(BrushDrawingMode);
-// qDebug("QGL2PaintEngineExPrivate::drawOutline()");
+ // Might need to call updateMatrix to re-calculate inverseScale
if (matrixDirty)
updateMatrix();
@@ -621,7 +592,7 @@ void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path)
vertexCoordinateArray.stops().last() += 1;
}
- prepareForDraw();
+ prepareForDraw(currentBrush->isOpaque());
drawVertexArrays(vertexCoordinateArray, GL_LINE_STRIP);
}
@@ -629,8 +600,9 @@ void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path)
// Assumes everything is configured for the brush you want to use
void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
{
- transferMode(DefaultMode);
+ transferMode(BrushDrawingMode);
+ // Might need to call updateMatrix to re-calculate inverseScale
if (matrixDirty)
updateMatrix();
@@ -639,13 +611,13 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
// Check to see if there's any hints
if (path.shape() == QVectorPath::RectangleHint) {
QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y());
- prepareForDraw();
+ prepareForDraw(currentBrush->isOpaque());
composite(rect);
}
else if (path.shape() == QVectorPath::EllipseHint) {
vertexCoordinateArray.clear();
vertexCoordinateArray.addPath(path, inverseScale);
- prepareForDraw();
+ prepareForDraw(currentBrush->isOpaque());
drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
}
else {
@@ -658,7 +630,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
// Stencil the brush onto the dest buffer
glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
glEnable(GL_STENCIL_TEST);
- prepareForDraw();
+ prepareForDraw(currentBrush->isOpaque());
composite(vertexCoordinateArray.boundingRect());
glDisable(GL_STENCIL_TEST);
@@ -738,32 +710,55 @@ void QGL2PaintEngineExPrivate::cleanStencilBuffer(const QGLRect& area)
glDisable(GL_STENCIL_TEST);
}
-void QGL2PaintEngineExPrivate::prepareForDraw()
+void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
{
- if (brushTextureDirty)
+ if (brushTextureDirty && mode != ImageDrawingMode)
updateBrushTexture();
if (compositionModeDirty)
updateCompositionMode();
- if (shaderManager->useCorrectShaderProg()) {
+ if (matrixDirty)
+ updateMatrix();
+
+ const bool stateHasOpacity = q->state()->opacity < 0.99f;
+ if ( (!srcPixelsAreOpaque || stateHasOpacity) &&
+ q->state()->compositionMode() != QPainter::CompositionMode_Source)
+ glEnable(GL_BLEND);
+ else
+ glDisable(GL_BLEND);
+
+ bool useGlobalOpacityUniform = stateHasOpacity;
+ if (stateHasOpacity && (mode != ImageDrawingMode)) {
+ // Using a brush
+ bool brushIsPattern = (currentBrush->style() >= Qt::Dense1Pattern) &&
+ (currentBrush->style() <= Qt::DiagCrossPattern);
+
+ if ((currentBrush->style() == Qt::SolidPattern) || brushIsPattern)
+ useGlobalOpacityUniform = false; // Global opacity handled by srcPixel shader
+ }
+ shaderManager->setUseGlobalOpacity(useGlobalOpacityUniform);
+
+
+ // If the shader program needs changing, we change it and mark all uniforms as dirty
+ if (shaderManager->shaderProgramDirty()) {
+ shaderManager->useCorrectShaderProg();
+
// The shader program has changed so mark all uniforms as dirty:
brushUniformsDirty = true;
- brushShaderMatrixUniformDirty = true;
+ shaderMatrixUniformDirty = true;
}
- if (brushUniformsDirty)
+ if (brushUniformsDirty && mode != ImageDrawingMode)
updateBrushUniforms();
- if (brushShaderMatrixUniformDirty) {
- shaderManager->brushShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
- brushShaderMatrixUniformDirty = false;
+ if (shaderMatrixUniformDirty) {
+ shaderManager->currentProgram()->setUniformValue("pmvMatrix", pmvMatrix);
+ shaderMatrixUniformDirty = false;
}
- if ((q->state()->opacity < 0.99f) || !currentBrush->isOpaque())
- glEnable(GL_BLEND);
- else
- glDisable(GL_BLEND);
+ if (useGlobalOpacityUniform)
+ shaderManager->currentProgram()->setUniformValue("globalOpacity", (GLfloat)q->state()->opacity);
}
void QGL2PaintEngineExPrivate::composite(const QGLRect& boundingRect)
@@ -823,6 +818,9 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
{
Q_D(QGL2PaintEngineEx);
+ if (brush.style() == Qt::NoBrush)
+ return;
+
ensureActive();
d->setBrush(&brush);
d->fill(path);
@@ -880,7 +878,6 @@ void QGL2PaintEngineEx::opacityChanged()
Q_D(QGL2PaintEngineEx);
Q_ASSERT(d->shaderManager);
- d->shaderManager->setUseGlobalOpacity(state()->opacity > 0.999);
d->brushUniformsDirty = true;
}
@@ -910,6 +907,7 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
d->transferMode(ImageDrawingMode);
QGLContext *ctx = d->ctx;
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
//FIXME: we should use hasAlpha() instead, but that's SLOW at the moment
@@ -929,6 +927,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const
d->transferMode(ImageDrawingMode);
QGLContext *ctx = d->ctx;
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
if ((state()->opacity < 0.99f) || image.hasAlphaChannel())
@@ -942,6 +941,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const
void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
{
Q_D(QGL2PaintEngineEx);
+
ensureActive();
QOpenGLPaintEngineState *s = state();
@@ -949,9 +949,6 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
bool drawCached = true;
- if (state()->pen.brush().style() != Qt::SolidPattern)
- drawCached = false;
-
if (s->matrix.type() > QTransform::TxTranslate)
drawCached = false;
@@ -969,21 +966,33 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
{
+ transferMode(TextDrawingMode);
+
Q_Q(QGL2PaintEngineEx);
QOpenGLPaintEngineState *s = q->state();
- transferMode(TextDrawingMode);
-
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
QTransform matrix;
matrix.translate(p.x(), p.y());
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat)
: QFontEngineGlyphCache::Raster_A8;
+ GLenum maskFormat = GL_RGBA;
+ if (glyphType == QFontEngineGlyphCache::Raster_A8) {
+ shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
+// maskFormat = GL_ALPHA;
+ }
+ else if (glyphType == QFontEngineGlyphCache::Raster_RGBMask)
+ shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMask);
+ //### TODO: Gamma correction
+ shaderManager->setTextureCoordsEnabled(true);
+
+
QImageTextureGlyphCache *cache =
(QImageTextureGlyphCache *) ti.fontEngine->glyphCache(glyphType, s->matrix);
if (!cache) {
@@ -999,24 +1008,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
if (image.isNull())
return;
- ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
-
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
-
- if (compositionModeDirty)
- updateCompositionMode();
-
- if (matrixDirty)
- updateMatrix();
-
- if (textShaderMatrixUniformDirty) {
- shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
- textShaderMatrixUniformDirty = false;
- }
-
- QColor col = premultiplyColor(s->pen.color(), (GLfloat)s->opacity);
- shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col;
-
GLfloat dx = 1.0 / image.width();
GLfloat dy = 1.0 / image.height();
@@ -1035,12 +1026,25 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
textureCoordinateArray.addRect(QRectF(c.x*dx, 1 - c.y*dy, c.w * dx, -c.h * dy));
}
+ glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+ ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+
+ QBrush pensBrush = q->state()->pen.brush();
+ setBrush(&pensBrush);
+
+ prepareForDraw(false); // Text always causes src pixels to be transparent
+
+ shaderManager->currentProgram()->setUniformValue("maskTexture", QT_MASK_TEXTURE_UNIT);
+
if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
+
+ setBrush(&(q->state()->brush)); //###
}
bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
@@ -1055,7 +1059,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
QSize sz = d->drawable.size();
d->width = sz.width();
d->height = sz.height();
- d->mode = DefaultMode;
+ d->mode = BrushDrawingMode;
qt_resolve_version_1_3_functions(d->ctx);
qt_resolve_glsl_extensions(d->ctx);
@@ -1065,11 +1069,11 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
if (d->last_engine) {
QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(d->last_engine);
- static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr)->transferMode(DefaultMode);
+ static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr)->transferMode(BrushDrawingMode);
}
if (!d->shaderManager)
- d->shaderManager = new QGLPEXShaderManager(d->ctx);
+ d->shaderManager = new QGLEngineShaderManager(d->ctx);
glViewport(0, 0, d->width, d->height);
@@ -1114,14 +1118,14 @@ bool QGL2PaintEngineEx::end()
QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(d->last_engine);
if (engine) {
QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr);
- p->transferMode(DefaultMode);
+ p->transferMode(BrushDrawingMode);
p->drawable.doneCurrent();
}
d->drawable.makeCurrent();
}
glUseProgram(0);
- d->transferMode(DefaultMode);
+ d->transferMode(BrushDrawingMode);
d->drawable.swapBuffers();
d->drawable.doneCurrent();
d->ctx->d_ptr->active_engine = d->last_engine;
@@ -1150,7 +1154,7 @@ void QGL2PaintEngineEx::ensureActive()
QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine);
if (engine) {
QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr);
- p->transferMode(DefaultMode);
+ p->transferMode(BrushDrawingMode);
p->drawable.doneCurrent();
}
d->drawable.makeCurrent();
@@ -1378,9 +1382,7 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state)
d->brushTextureDirty = true;
d->brushUniformsDirty = true;
d->simpleShaderMatrixUniformDirty = true;
- d->brushShaderMatrixUniformDirty = true;
- d->imageShaderMatrixUniformDirty = true;
- d->textShaderMatrixUniformDirty = true;
+ d->shaderMatrixUniformDirty = true;
}
QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 9006a32..88af516 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -25,12 +25,16 @@ HEADERS += qgl.h \
qglcolormap.h \
qglpixelbuffer.h \
qglframebufferobject.h \
+ qglpixmapfilter_p.h \
+ qglshaderprogram.h
SOURCES += qgl.cpp \
qglcolormap.cpp \
qglpixelbuffer.cpp \
qglframebufferobject.cpp \
qglextensions.cpp \
+ qglpixmapfilter.cpp \
+ qglshaderprogram.cpp
#!contains(QT_CONFIG, opengles2) {
# HEADERS += qpaintengine_opengl_p.h
@@ -39,16 +43,15 @@ SOURCES += qgl.cpp \
#contains(QT_CONFIG, opengles2) {
SOURCES += gl2paintengineex/qglgradientcache.cpp \
- gl2paintengineex/qglpexshadermanager.cpp \
- gl2paintengineex/qglshader.cpp \
+ gl2paintengineex/qglengineshadermanager.cpp \
gl2paintengineex/qgl2pexvertexarray.cpp \
gl2paintengineex/qpaintengineex_opengl2.cpp
HEADERS += gl2paintengineex/qglgradientcache_p.h \
- gl2paintengineex/qglpexshadermanager_p.h \
- gl2paintengineex/qglshader_p.h \
+ gl2paintengineex/qglengineshadermanager_p.h \
gl2paintengineex/qgl2pexvertexarray_p.h \
- gl2paintengineex/qpaintengineex_opengl2_p.h
+ gl2paintengineex/qpaintengineex_opengl2_p.h \
+ gl2paintengineex/qglengineshadersource_p.h
#}
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index e6ac043..5fda346 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -153,55 +153,179 @@ 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"));
-
- glGetActiveAttrib = (_glGetActiveAttrib) ctx->getProcAddress(QLatin1String("glGetActiveAttrib"));
- glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
- glGetActiveUniform = (_glGetActiveUniform) ctx->getProcAddress(QLatin1String("glGetActiveUniform"));
- glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
- glUniform1f = (_glUniform1f) ctx->getProcAddress(QLatin1String("glUniform1f"));
- glUniform2f = (_glUniform2f) ctx->getProcAddress(QLatin1String("glUniform2f"));
- glUniform4f = (_glUniform4f) ctx->getProcAddress(QLatin1String("glUniform4f"));
- glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
- glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
- glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
- glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
- glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
- glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
- glStencilOpSeparate = (_glStencilOpSeparate) ctx->getProcAddress(QLatin1String("glStencilOpSeparate"));
-
- return glCreateShader && glShaderSource && glCompileShader && glDeleteProgram &&
- glCreateProgram && glAttachShader && glDetachShader && glLinkProgram && glUseProgram &&
- glDeleteProgram && glGetShaderInfoLog && glGetShaderiv && glGetProgramiv && glGetUniformLocation &&
- glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv &&
- glGetActiveAttrib && glGetAttribLocation && glGetActiveUniform && glGetProgramInfoLog &&
- glUniform1f && glUniform2f && glUniform4f &&
- glUniformMatrix2fv && glUniformMatrix3fv && glUniformMatrix4fv &&
- glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glStencilOpSeparate;
+ 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"));
+
+ glGetActiveUniform = (_glGetActiveUniform) ctx->getProcAddress(QLatin1String("glGetActiveUniform"));//### REMOVE
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
+ glUniform4f = (_glUniform4f) ctx->getProcAddress(QLatin1String("glUniform4f")); //### REMOVE
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
+ glUniform2f = (_glUniform2f) ctx->getProcAddress(QLatin1String("glUniform2f")); //### REMOVE
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
+ glUniform1f = (_glUniform1f) ctx->getProcAddress(QLatin1String("glUniform1f")); //### REMOVE
+ 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"));
+
+ glGetActiveAttrib = (_glGetActiveAttrib) ctx->getProcAddress(QLatin1String("glGetActiveAttrib")); //### REMOVE
+ 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"));
+
+ glStencilOpSeparate = (_glStencilOpSeparate) ctx->getProcAddress(QLatin1String("glStencilOpSeparate")); //### Not really a glsl extension, but needed for gl2
+
+ } 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"));
+
+ glGetActiveUniform = (_glGetActiveUniform) ctx->getProcAddress(QLatin1String("glGetActiveUniformARB"));//### REMOVE
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocationARB"));
+ glUniform4f = (_glUniform4f) ctx->getProcAddress(QLatin1String("glUniform4fARB")); //### REMOVE
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fvARB"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fvARB"));
+ glUniform2f = (_glUniform2f) ctx->getProcAddress(QLatin1String("glUniform2fARB")); //### REMOVE
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fvARB"));
+ glUniform1f = (_glUniform1f) ctx->getProcAddress(QLatin1String("glUniform1fARB")); //### REMOVE
+ 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"));
+
+ glGetActiveAttrib = (_glGetActiveAttrib) ctx->getProcAddress(QLatin1String("glGetActiveAttribARB")); //### REMOVE
+ 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"));
+
+ glStencilOpSeparate = 0; //### Was never an ARB extension but went strait into OpenGL 2.0
+ }
+
+ // 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 &&
+ glGetActiveUniform && //### REMOVE
+ glGetUniformLocation &&
+ glUniform1f && //### REMOVE
+ glUniform1fv &&
+ glUniform2f && //### REMOVE
+ glUniform2fv &&
+ glUniform3fv &&
+ glUniform4f && //### REMOVE
+ glUniform4fv &&
+ glUniform1i &&
+ glUniform1iv &&
+ glUniformMatrix2fv &&
+ glUniformMatrix3fv &&
+ glUniformMatrix4fv &&
+ glGetActiveAttrib && //### REMOVE
+ glBindAttribLocation &&
+ glGetAttribLocation &&
+ glVertexAttrib1fv &&
+ glVertexAttrib2fv &&
+ glVertexAttrib3fv &&
+ glVertexAttrib4fv &&
+ glVertexAttribPointer &&
+ glDisableVertexAttribArray &&
+ glEnableVertexAttribArray &&
+ glStencilOpSeparate;
+#endif
}
QT_END_NAMESPACE
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index cd35eb0..9249730 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -96,8 +96,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);
@@ -105,10 +107,13 @@ 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, const GLfloat *);
@@ -116,6 +121,29 @@ 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 );
@@ -182,10 +210,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;
@@ -193,10 +224,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;
@@ -204,6 +238,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;
@@ -261,11 +321,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;
@@ -273,10 +336,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;
@@ -284,6 +350,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;
@@ -320,18 +412,10 @@ struct QGLExtensionFuncs
_glUnmapBufferARB qt_glUnmapBufferARB;
_glGetActiveAttrib qt_glGetActiveAttrib;
- _glGetAttribLocation qt_glGetAttribLocation;
_glGetActiveUniform qt_glGetActiveUniform;
- _glGetProgramInfoLog qt_glGetProgramInfoLog;
_glUniform1f qt_glUniform1f;
_glUniform2f qt_glUniform2f;
_glUniform4f qt_glUniform4f;
- _glUniformMatrix2fv qt_glUniformMatrix2fv;
- _glUniformMatrix3fv qt_glUniformMatrix3fv;
- _glUniformMatrix4fv qt_glUniformMatrix4fv;
- _glEnableVertexAttribArray qt_glEnableVertexAttribArray;
- _glDisableVertexAttribArray qt_glDisableVertexAttribArray;
- _glVertexAttribPointer qt_glVertexAttribPointer;
_glStencilOpSeparate qt_glStencilOpSeparate;
};
@@ -600,10 +684,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
@@ -611,10 +699,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
@@ -622,6 +713,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
#define glGetActiveAttrib QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetActiveAttrib
#define glGetAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetAttribLocation
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index 8a64515..87abf60 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,110 +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);
-}
-
-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:
@@ -192,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>
@@ -206,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;
@@ -298,10 +179,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
@@ -309,10 +192,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();
@@ -320,7 +203,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");
@@ -356,7 +239,7 @@ QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
code.append(" }\n");
code.append(" gl_FragColor = sum;\n");
code.append("}");
- return QLatin1String(code);
+ return code;
}
QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter()
@@ -388,10 +271,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();
@@ -401,10 +286,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..c2be1be
--- /dev/null
+++ b/src/opengl/qglshaderprogram.cpp
@@ -0,0 +1,2960 @@
+/****************************************************************************
+**
+** 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 \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLuint value)
+{
+ if (location != -1)
+ glUniform1i(location, value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLuint 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
+ the x() & y() coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QPoint& point)
+{
+ if (location != -1) {
+ GLfloat values[4] = {point.x(), point.y()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context to
+ the x() & y() coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QPoint& point)
+{
+ setUniformValue(uniformLocation(name), point);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the x() & y() coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QPointF& point)
+{
+ if (location != -1) {
+ GLfloat values[4] = {point.x(), point.y()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context to
+ the x() & y() coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QPointF& point)
+{
+ setUniformValue(uniformLocation(name), point);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the width() & height() of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QSize& size)
+{
+ if (location != -1) {
+ GLfloat values[4] = {size.width(), size.width()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context to
+ the width() & height() of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QSize& size)
+{
+ setUniformValue(uniformLocation(name), size);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the width() & height() of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QSizeF& size)
+{
+ if (location != -1) {
+ GLfloat values[4] = {size.width(), size.height()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context to
+ the width() & height() of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QSizeF& size)
+{
+ setUniformValue(uniformLocation(name), size);
+}
+
+/*!
+ 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..508fd96
--- /dev/null
+++ b/src/opengl/qglshaderprogram.h
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** 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, GLuint 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 QPoint& point);
+ void setUniformValue(int location, const QPointF& point);
+ void setUniformValue(int location, const QSize& size);
+ void setUniformValue(int location, const QSizeF& size);
+ 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, GLuint 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 QPoint& point);
+ void setUniformValue(const char *name, const QPointF& point);
+ void setUniformValue(const char *name, const QSize& size);
+ void setUniformValue(const char *name, const QSizeF& size);
+ 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