summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-02-01 13:57:38 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-02-01 13:57:38 (GMT)
commit5067683704580fcfedef4e68f19acedb133936e8 (patch)
tree9ed5acfa397b093fd726742ae3c478c2f21223bc /src/opengl
parent1b4bb02fcb3da77ddfa6281365ba3210aab9daad (diff)
parent11d2c8f96697adc93ccd82e3db1de6ecde025eff (diff)
downloadQt-5067683704580fcfedef4e68f19acedb133936e8.zip
Qt-5067683704580fcfedef4e68f19acedb133936e8.tar.gz
Qt-5067683704580fcfedef4e68f19acedb133936e8.tar.bz2
Merge branch 'qt-master-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration into master-integration
* 'qt-master-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration: (160 commits) audiodevices example: no devices available Assistant: Fix unintended tr context change. Add QFontMetrics benchmark. Fixed `make test' for xmlpatternsxqts. Doc: Put the correct images with the D-Bus and Embedded Linux sections. Call cheaper clear() instead of assigning new QString() Fix a regression: icons with slightly wrong ICO header did not load. Fix some foreach usage to use const refs Designer: Fix source code scanning issues. googlesuggest example: Add newline to end of file Core classes, examples, demos: Some changes from string to char Fix header labels on mac with rtl Fixed an endless loop if printing web pages. doc: Fixed the last qdoc errors. don't build unneeded QtDesigner parts on Windows CE doc: Document the "Type" enum value as a const in variable. Add additional text and painting benchmarks. Better support for user-generated binary shaders don't falsely complain about mismatched codecfortr Fix QSettings default paths not being initialized when setPath() is called ...
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp10
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h5
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h678
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp25
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h2
-rw-r--r--src/opengl/qgl.cpp29
-rw-r--r--src/opengl/qglshaderprogram.cpp38
-rw-r--r--src/opengl/qpixmapdata_gl.cpp14
8 files changed, 443 insertions, 358 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 556b888..8183f08 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -184,6 +184,9 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
simpleShaderProg->addShader(vertexShader);
simpleShaderProg->addShader(fragShader);
simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
+ simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
+ simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
simpleShaderProg->link();
if (!simpleShaderProg->isLinked()) {
qCritical() << "Errors linking simple shader:"
@@ -324,6 +327,11 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
if (newProg->useOpacityAttribute)
newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
+ if (newProg->usePmvMatrix) {
+ newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
+ newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
+ newProg->program->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
+ }
newProg->program->link();
if (!newProg->program->isLinked()) {
@@ -424,7 +432,6 @@ GLuint QGLEngineShaderManager::getUniformLocation(Uniform id)
"patternColor",
"globalOpacity",
"depth",
- "pmvMatrix",
"maskTexture",
"fragmentColor",
"linearData",
@@ -743,6 +750,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg()
}
requiredProgram.useTextureCoords = texCoords;
requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
+ requiredProgram.usePmvMatrix = true;
// At this point, requiredProgram is fully populated so try to find the program in the cache
currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index c52e5c0..3ab4ebe 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -253,6 +253,9 @@ struct QGLEngineCachedShaderProg
static const GLuint QT_VERTEX_COORDS_ATTR = 0;
static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
static const GLuint QT_OPACITY_ATTR = 2;
+static const GLuint QT_PMV_MATRIX_1_ATTR = 3;
+static const GLuint QT_PMV_MATRIX_2_ATTR = 4;
+static const GLuint QT_PMV_MATRIX_3_ATTR = 5;
class QGLEngineShaderProg;
@@ -397,6 +400,7 @@ public:
bool useTextureCoords;
bool useOpacityAttribute;
+ bool usePmvMatrix;
bool operator==(const QGLEngineShaderProg& other) {
// We don't care about the program
@@ -431,7 +435,6 @@ public:
PatternColor,
GlobalOpacity,
Depth,
- PmvMatrix,
MaskTexture,
FragmentColor,
LinearData,
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index d9a61e9..ee04166 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -63,210 +63,229 @@ QT_BEGIN_NAMESPACE
QT_MODULE(OpenGL)
-static const char* const qglslMainVertexShader = "\
- uniform highp float depth;\
- void setPosition();\
- void main(void)\
- {\
- setPosition();\
- gl_Position.z = depth * gl_Position.w;\
- }";
-
-static const char* const qglslMainWithTexCoordsVertexShader = "\
- attribute highp vec2 textureCoordArray; \
- varying highp vec2 textureCoords; \
- uniform highp float depth;\
- void setPosition();\
- void main(void) \
- {\
- setPosition();\
- gl_Position.z = depth * gl_Position.w;\
- textureCoords = textureCoordArray; \
- }";
-
-static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\
- attribute highp vec2 textureCoordArray; \
- attribute lowp float opacityArray; \
- varying highp vec2 textureCoords; \
- varying lowp float opacity; \
- uniform highp float depth; \
- void setPosition(); \
- void main(void) \
- { \
- setPosition(); \
- gl_Position.z = depth * gl_Position.w; \
- textureCoords = textureCoordArray; \
- opacity = opacityArray; \
- }";
+static const char* const qglslMainVertexShader = "\n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ }\n";
+
+static const char* const qglslMainWithTexCoordsVertexShader = "\n\
+ attribute highp vec2 textureCoordArray; \n\
+ varying highp vec2 textureCoords; \n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ textureCoords = textureCoordArray; \n\
+ }\n";
+
+static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\n\
+ attribute highp vec2 textureCoordArray; \n\
+ attribute lowp float opacityArray; \n\
+ varying highp vec2 textureCoords; \n\
+ varying lowp float opacity; \n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ textureCoords = textureCoordArray; \n\
+ opacity = opacityArray; \n\
+ }\n";
// NOTE: We let GL do the perspective correction so texture lookups in the fragment
// shader are also perspective corrected.
-static const char* const qglslPositionOnlyVertexShader = "\
- attribute highp vec2 vertexCoordsArray;\
- uniform highp mat3 pmvMatrix;\
- void setPosition(void)\
- {\
- vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \
- gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \
- }";
-
-static const char* const qglslUntransformedPositionVertexShader = "\
- attribute highp vec4 vertexCoordsArray;\
- void setPosition(void)\
- {\
- gl_Position = vertexCoordsArray;\
- }";
+static const char* const qglslPositionOnlyVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\
+ }\n";
+
+static const char* const qglslUntransformedPositionVertexShader = "\n\
+ attribute highp vec4 vertexCoordsArray; \n\
+ void setPosition(void) \n\
+ { \n\
+ gl_Position = vertexCoordsArray; \n\
+ }\n";
// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
-static const char* const qglslPositionWithPatternBrushVertexShader = "\
- attribute highp vec2 vertexCoordsArray; \
- uniform highp mat3 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform highp vec2 invertedTextureSize; \
- uniform highp mat3 brushTransform; \
- varying highp vec2 patternTexCoords; \
- void setPosition(void) { \
- vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \
- gl_Position.xy = transformedPos.xy / transformedPos.z; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
- patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \
- }";
+static const char* const qglslPositionWithPatternBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp vec2 invertedTextureSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying highp vec2 patternTexCoords; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\
+ }\n";
static const char* const qglslAffinePositionWithPatternBrushVertexShader
= qglslPositionWithPatternBrushVertexShader;
-static const char* const qglslPatternBrushSrcFragmentShader = "\
- uniform lowp sampler2D brushTexture;\
- uniform lowp vec4 patternColor; \
- varying highp vec2 patternTexCoords;\
- lowp vec4 srcPixel() { \
- return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \
+static const char* const qglslPatternBrushSrcFragmentShader = "\n\
+ uniform lowp sampler2D brushTexture; \n\
+ uniform lowp vec4 patternColor; \n\
+ varying highp vec2 patternTexCoords;\n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\
}\n";
// Linear Gradient Brush
-static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\
- attribute highp vec2 vertexCoordsArray; \
- uniform highp mat3 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform highp vec3 linearData; \
- uniform highp mat3 brushTransform; \
- varying mediump float index; \
- void setPosition() { \
- vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \
- gl_Position.xy = transformedPos.xy / transformedPos.z; \
- 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 = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
- index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \
- }";
+static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp vec3 linearData; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying mediump float index; \n\
+ void setPosition() \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\
+ }\n";
static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader
= qglslPositionWithLinearGradientBrushVertexShader;
-static const char* const qglslLinearGradientBrushSrcFragmentShader = "\
- uniform lowp sampler2D brushTexture; \
- varying mediump float index; \
- lowp vec4 srcPixel() { \
- mediump vec2 val = vec2(index, 0.5); \
- return texture2D(brushTexture, val); \
+static const char* const qglslLinearGradientBrushSrcFragmentShader = "\n\
+ uniform lowp sampler2D brushTexture; \n\
+ varying mediump float index; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ mediump vec2 val = vec2(index, 0.5); \n\
+ return texture2D(brushTexture, val); \n\
}\n";
// Conical Gradient Brush
-static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\
- attribute highp vec2 vertexCoordsArray;\
- uniform highp mat3 pmvMatrix;\
- uniform mediump vec2 halfViewportSize; \
- uniform highp mat3 brushTransform; \
- varying highp vec2 A; \
- void setPosition(void)\
- {\
- vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \
- gl_Position.xy = transformedPos.xy / transformedPos.z; \
- 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 = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
- A = hTexCoords.xy * invertedHTexCoordsZ; \
- }";
+static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying highp vec2 A; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ A = hTexCoords.xy * invertedHTexCoordsZ; \n\
+ }\n";
static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader
= qglslPositionWithConicalGradientBrushVertexShader;
static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\
#define INVERSE_2PI 0.1591549430918953358 \n\
- uniform lowp 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)); \
- }";
+ uniform lowp sampler2D brushTexture; \n\
+ uniform mediump float angle; \n\
+ varying highp vec2 A; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ highp float t; \n\
+ if (abs(A.y) == abs(A.x)) \n\
+ t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\
+ else \n\
+ t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\
+ return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\
+ }\n";
// Radial Gradient Brush
-static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\
- attribute highp vec2 vertexCoordsArray;\
- uniform highp mat3 pmvMatrix;\
- uniform mediump vec2 halfViewportSize; \
- uniform highp mat3 brushTransform; \
- uniform highp vec2 fmp; \
- varying highp float b; \
- varying highp vec2 A; \
- void setPosition(void) \
- {\
- vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \
- gl_Position.xy = transformedPos.xy / transformedPos.z; \
- 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 = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
- A = hTexCoords.xy * invertedHTexCoordsZ; \
- b = 2.0 * dot(A, fmp); \
- }";
+static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray;\n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ uniform highp vec2 fmp; \n\
+ varying highp float b; \n\
+ varying highp vec2 A; \n\
+ void setPosition(void) \n\
+ {\n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ A = hTexCoords.xy * invertedHTexCoordsZ; \n\
+ b = 2.0 * dot(A, fmp); \n\
+ }\n";
static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader
= qglslPositionWithRadialGradientBrushVertexShader;
-static const char* const qglslRadialGradientBrushSrcFragmentShader = "\
- uniform lowp 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); \
- }";
+static const char* const qglslRadialGradientBrushSrcFragmentShader = "\n\
+ uniform lowp sampler2D brushTexture; \n\
+ uniform highp float fmp2_m_radius2; \n\
+ uniform highp float inverse_2_fmp2_m_radius2; \n\
+ varying highp float b; \n\
+ varying highp vec2 A; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ highp float c = -dot(A, A); \n\
+ highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \n\
+ return texture2D(brushTexture, val); \n\
+ }\n";
// Texture Brush
-static const char* const qglslPositionWithTextureBrushVertexShader = "\
- attribute highp vec2 vertexCoordsArray; \
- uniform highp mat3 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform highp vec2 invertedTextureSize; \
- uniform highp mat3 brushTransform; \
- varying highp vec2 textureCoords; \
- void setPosition(void) { \
- vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \
- gl_Position.xy = transformedPos.xy / transformedPos.z; \
- 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 = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
- textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \
- }";
+static const char* const qglslPositionWithTextureBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp vec2 invertedTextureSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying highp vec2 textureCoords; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\
+ }\n";
static const char* const qglslAffinePositionWithTextureBrushVertexShader
= qglslPositionWithTextureBrushVertexShader;
@@ -275,148 +294,165 @@ static const char* const qglslAffinePositionWithTextureBrushVertexShader
// OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
// we emulate GL_REPEAT by only taking the fractional part of the texture coords.
// TODO: Special case POT textures which don't need this emulation
-static const char* const qglslTextureBrushSrcFragmentShader = "\
- varying highp vec2 textureCoords; \
- uniform lowp sampler2D brushTexture; \
- lowp vec4 srcPixel() { \
- return texture2D(brushTexture, fract(textureCoords)); \
- }";
+static const char* const qglslTextureBrushSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp sampler2D brushTexture; \n\
+ lowp vec4 srcPixel() { \n\
+ return texture2D(brushTexture, fract(textureCoords)); \n\
+ }\n";
#else
-static const char* const qglslTextureBrushSrcFragmentShader = "\
- varying highp vec2 textureCoords; \
- uniform lowp sampler2D brushTexture; \
- lowp vec4 srcPixel() { \
- return texture2D(brushTexture, textureCoords); \
- }";
+static const char* const qglslTextureBrushSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp sampler2D brushTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return texture2D(brushTexture, textureCoords); \n\
+ }\n";
#endif
-static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\
- varying highp vec2 textureCoords; \
- uniform lowp vec4 patternColor; \
- uniform lowp sampler2D brushTexture; \
- lowp vec4 srcPixel() { \
- return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \
- }";
+static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp vec4 patternColor; \n\
+ uniform lowp sampler2D brushTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \n\
+ }\n";
// 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 lowp sampler2D imageTexture; \
- lowp vec4 srcPixel() { \
- return texture2D(imageTexture, textureCoords); \
- }";
-
-static const char* const qglslCustomSrcFragmentShader = "\
- varying highp vec2 textureCoords; \
- uniform lowp sampler2D imageTexture; \
- lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \
- lowp vec4 srcPixel() { \
- return customShader(imageTexture, textureCoords); \
- }";
-
-static const char* const qglslImageSrcWithPatternFragmentShader = "\
- varying highp vec2 textureCoords; \
- uniform lowp vec4 patternColor; \
- uniform lowp sampler2D imageTexture; \
- lowp vec4 srcPixel() { \
- return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \
- }\n";
-
-static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\
- varying highp vec2 textureCoords; \
- uniform lowp 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 vec4(0.98, 0.06, 0.75, 1.0); \
- }";
-
-static const char* const qglslMainFragmentShader_ImageArrays = "\
- varying lowp float opacity; \
- lowp vec4 srcPixel(); \
- void main() { \
- gl_FragColor = srcPixel() * opacity; \
- }";
-
-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 = applyMask(compose(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 = applyMask(compose(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 lowp sampler2D maskTexture;\
- lowp vec4 applyMask(lowp vec4 src) \
- {\
- lowp vec4 mask = texture2D(maskTexture, textureCoords); \
- return src * mask.a; \
- }";
+static const char* const qglslSolidBrushSrcFragmentShader = "\n\
+ uniform lowp vec4 fragmentColor; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return fragmentColor; \n\
+ }\n";
+
+static const char* const qglslImageSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return texture2D(imageTexture, textureCoords); \n\
+ }\n";
+
+static const char* const qglslCustomSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp sampler2D imageTexture; \n\
+ lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return customShader(imageTexture, textureCoords); \n\
+ }\n";
+
+static const char* const qglslImageSrcWithPatternFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp vec4 patternColor; \n\
+ uniform lowp sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\
+ }\n";
+
+static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\
+ sample.rgb = sample.rgb * sample.a; \n\
+ return sample; \n\
+ }\n";
+
+static const char* const qglslShockingPinkSrcFragmentShader = "\n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return vec4(0.98, 0.06, 0.75, 1.0); \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_ImageArrays = "\n\
+ varying lowp float opacity; \n\
+ lowp vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = srcPixel() * opacity; \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_CMO = "\n\
+ uniform lowp float globalOpacity; \n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 applyMask(lowp vec4); \n\
+ lowp vec4 compose(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_CM = "\n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 applyMask(lowp vec4); \n\
+ lowp vec4 compose(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = applyMask(compose(srcPixel())); \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_MO = "\n\
+ uniform lowp float globalOpacity; \n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 applyMask(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_M = "\n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 applyMask(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = applyMask(srcPixel()); \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_CO = "\n\
+ uniform lowp float globalOpacity; \n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 compose(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = compose(srcPixel()*globalOpacity); \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_C = "\n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 compose(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = compose(srcPixel()); \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader_O = "\n\
+ uniform lowp float globalOpacity; \n\
+ lowp vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = srcPixel()*globalOpacity; \n\
+ }\n";
+
+static const char* const qglslMainFragmentShader = "\n\
+ lowp vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = srcPixel(); \n\
+ }\n";
+
+static const char* const qglslMaskFragmentShader = "\n\
+ varying highp vec2 textureCoords;\n\
+ uniform lowp sampler2D maskTexture;\n\
+ lowp vec4 applyMask(lowp vec4 src) \n\
+ {\n\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
+ return src * mask.a; \n\
+ }\n";
// For source over with subpixel antialiasing, the final color is calculated per component as follows
// (.a is alpha component, .c is red, green or blue component):
@@ -433,23 +469,23 @@ static const char* const qglslMaskFragmentShader = "\
// dest.c = dest.c * (1 - mask.c) + src.c * alpha
//
-static const char* const qglslRgbMaskFragmentShaderPass1 = "\
- varying highp vec2 textureCoords;\
- uniform lowp sampler2D maskTexture;\
- lowp vec4 applyMask(lowp vec4 src) \
- {\
- lowp vec4 mask = texture2D(maskTexture, textureCoords); \
- return src.a * mask; \
- }";
-
-static const char* const qglslRgbMaskFragmentShaderPass2 = "\
- varying highp vec2 textureCoords;\
- uniform lowp sampler2D maskTexture;\
- lowp vec4 applyMask(lowp vec4 src) \
- {\
- lowp vec4 mask = texture2D(maskTexture, textureCoords); \
- return src * mask; \
- }";
+static const char* const qglslRgbMaskFragmentShaderPass1 = "\n\
+ varying highp vec2 textureCoords;\n\
+ uniform lowp sampler2D maskTexture;\n\
+ lowp vec4 applyMask(lowp vec4 src) \n\
+ { \n\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
+ return src.a * mask; \n\
+ }\n";
+
+static const char* const qglslRgbMaskFragmentShaderPass2 = "\n\
+ varying highp vec2 textureCoords;\n\
+ uniform lowp sampler2D maskTexture;\n\
+ lowp vec4 applyMask(lowp vec4 src) \n\
+ { \n\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
+ return src * mask; \n\
+ }\n";
/*
Left to implement:
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 5e41cc1..24560d1 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -169,12 +169,6 @@ void QGL2PaintEngineExPrivate::useSimpleShader()
if (matrixDirty)
updateMatrix();
-
- if (simpleShaderMatrixUniformDirty) {
- const GLuint location = shaderManager->simpleProgram()->uniformLocation("pmvMatrix");
- glUniformMatrix3fv(location, 1, GL_FALSE, (GLfloat*)pmvMatrix);
- simpleShaderMatrixUniformDirty = false;
- }
}
void QGL2PaintEngineExPrivate::updateBrushTexture()
@@ -393,9 +387,11 @@ void QGL2PaintEngineExPrivate::updateMatrix()
matrixDirty = false;
- // The actual data has been updated so both shader program's uniforms need updating
- simpleShaderMatrixUniformDirty = true;
- shaderMatrixUniformDirty = true;
+ // Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only
+ // need to do this once for every matrix change and persists across all shader programs.
+ glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]);
+ glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]);
+ glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]);
dasher.setInvScale(inverseScale);
stroker.setInvScale(inverseScale);
@@ -1033,18 +1029,12 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
if (changed) {
// The shader program has changed so mark all uniforms as dirty:
brushUniformsDirty = true;
- shaderMatrixUniformDirty = true;
opacityUniformDirty = true;
}
if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
updateBrushUniforms();
- if (shaderMatrixUniformDirty) {
- glUniformMatrix3fv(location(QGLEngineShaderManager::PmvMatrix), 1, GL_FALSE, (GLfloat*)pmvMatrix);
- shaderMatrixUniformDirty = false;
- }
-
if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity);
opacityUniformDirty = false;
@@ -2060,11 +2050,8 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state)
if (old_state == s || old_state->renderHintsChanged)
renderHintsChanged();
- if (old_state == s || old_state->matrixChanged) {
+ if (old_state == s || old_state->matrixChanged)
d->matrixDirty = true;
- d->simpleShaderMatrixUniformDirty = true;
- d->shaderMatrixUniformDirty = true;
- }
if (old_state == s || old_state->compositionModeChanged)
d->compositionModeDirty = true;
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index e3d0bfc..35c88f4 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -252,8 +252,6 @@ public:
bool compositionModeDirty;
bool brushTextureDirty;
bool brushUniformsDirty;
- bool simpleShaderMatrixUniformDirty;
- bool shaderMatrixUniformDirty;
bool opacityUniformDirty;
bool stencilClean; // Has the stencil not been used for clipping so far?
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index b7139a2..bb76f1a 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -4494,6 +4494,13 @@ static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str,
\note This function temporarily disables depth-testing when the
text is drawn.
+ \note This function can only be used inside a
+ QPainter::beginNativePainting()/QPainter::endNativePainting() block
+ if the default OpenGL paint engine is QPaintEngine::OpenGL. To make
+ QPaintEngine::OpenGL the default GL engine, call
+ QGL::setPreferredPaintEngine(QPaintEngine::OpenGL) before the
+ QApplication constructor.
+
\l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
*/
@@ -4513,8 +4520,17 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font,
bool auto_swap = autoBufferSwap();
QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
- qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
+
QPaintEngine *engine = paintEngine();
+ if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) {
+ qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is"
+ " active on the same device is not allowed.");
+ return;
+ }
+
+ // this changes what paintEngine() returns
+ qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
+ engine = paintEngine();
QPainter *p;
bool reuse_painter = false;
if (engine->isActive()) {
@@ -4607,8 +4623,17 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con
win_y = height - win_y; // y is inverted
QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
- qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
QPaintEngine *engine = paintEngine();
+
+ if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) {
+ qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is"
+ " active on the same device is not allowed.");
+ return;
+ }
+
+ // this changes what paintEngine() returns
+ qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
+ engine = paintEngine();
QPainter *p;
bool reuse_painter = false;
bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 5e2f1f5..79484fa 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -106,6 +106,19 @@ QT_BEGIN_NAMESPACE
\snippet doc/src/snippets/code/src_opengl_qglshaderprogram.cpp 2
+ \section1 Binary shaders and programs
+
+ Binary shaders may be specified using \c{glShaderBinary()} on
+ the return value from QGLShader::shaderId(). The QGLShader instance
+ containing the binary can then be added to the shader program with
+ addShader() and linked in the usual fashion with link().
+
+ Binary programs may be specified using \c{glProgramBinaryOES()}
+ on the return value from programId(). Then the application should
+ call link(), which will notice that the program has already been
+ specified and linked, allowing other operations to be performed
+ on the shader program.
+
\sa QGLShader
*/
@@ -632,8 +645,6 @@ bool QGLShaderProgram::addShader(QGLShader *shader)
qWarning("QGLShaderProgram::addShader: Program and shader are not associated with same context.");
return false;
}
- if (!shader->d_func()->compiled)
- return false;
if (!shader->d_func()->shaderGuard.id())
return false;
glAttachShader(d->programGuard.id(), shader->d_func()->shaderGuard.id());
@@ -820,8 +831,20 @@ bool QGLShaderProgram::link()
GLuint program = d->programGuard.id();
if (!program)
return false;
+ GLint value;
+ if (d->shaders.isEmpty()) {
+ // If there are no explicit shaders, then it is possible that the
+ // application added a program binary with glProgramBinaryOES(),
+ // or otherwise populated the shaders itself. Check to see if the
+ // program is already linked and bail out if so.
+ value = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ if (d->linked)
+ return true;
+ }
glLinkProgram(program);
- GLint value = 0;
+ value = 0;
glGetProgramiv(program, GL_LINK_STATUS, &value);
d->linked = (value != 0);
value = 0;
@@ -928,6 +951,15 @@ void QGLShaderProgram::release()
GLuint QGLShaderProgram::programId() const
{
Q_D(const QGLShaderProgram);
+ GLuint id = d->programGuard.id();
+ if (id)
+ return id;
+
+ // Create the identifier if we don't have one yet. This is for
+ // applications that want to create the attached shader configuration
+ // themselves, particularly those using program binaries.
+ if (!const_cast<QGLShaderProgram *>(this)->init())
+ return 0;
return d->programGuard.id();
}
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index 6d47687..aa80664 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -252,10 +252,6 @@ QGLPixmapData::QGLPixmapData(PixelType type)
{
setSerialNumber(++qt_gl_pixmap_serial);
m_glDevice.setPixmapData(this);
-
- // Set InteralBindOptions minus the memory managed, since this
- // QGLTexture is not managed as part of the internal texture cache
- m_texture.options = QGLContext::PremultipliedAlphaBindOption;
}
QGLPixmapData::~QGLPixmapData()
@@ -344,18 +340,18 @@ void QGLPixmapData::ensureCreated() const
}
if (!m_source.isNull()) {
- glBindTexture(target, m_texture.id);
if (external_format == GL_RGB) {
- const QImage tx = m_source.convertToFormat(QImage::Format_RGB888);
+ const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true);
+
+ glBindTexture(target, m_texture.id);
glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
GL_UNSIGNED_BYTE, tx.bits());
} else {
const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
+
+ glBindTexture(target, m_texture.id);
glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
GL_UNSIGNED_BYTE, tx.bits());
- // convertToGLFormat will flip the Y axis, so it needs to
- // be drawn upside down
- m_texture.options |= QGLContext::InvertedYBindOption;
}
if (useFramebufferObjects())