summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorTom Cooksey <thomas.cooksey@nokia.com>2009-12-22 09:57:19 (GMT)
committerTom Cooksey <thomas.cooksey@nokia.com>2009-12-22 14:59:12 (GMT)
commit8908c2575b76789652aab4f623d60734707c3a54 (patch)
tree6a9ac63774e868cdc5c0e9831a88ea7854a9dfaf /src/opengl
parentb784d4991b186037ccd2b60ae3101697a2251160 (diff)
downloadQt-8908c2575b76789652aab4f623d60734707c3a54.zip
Qt-8908c2575b76789652aab4f623d60734707c3a54.tar.gz
Qt-8908c2575b76789652aab4f623d60734707c3a54.tar.bz2
Use 3x3 PMV matrices rather than 4x4 in the GL2 engine
QGraphicsView based applications will set a new transform for every item before it's painted. This leads to lots of updates to the PMV matrix. So switching to a 3x3 rather than a 4x4 gives us less data to pass to GL for each QGraphicsItem which gets rendered. It also means the vertex shader is more efficient. However, this patch only gives a maximum 2.5% speed improvement on the SGX, which seems to be only due to the faster vertex shader rather than the reduced amount of data we pass to GL. Reviewed-By: Kim
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h66
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp58
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h2
3 files changed, 62 insertions, 64 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index 2407979..46de124 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -99,12 +99,15 @@ static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\
opacity = opacityArray; \
}";
+// 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 vec4 vertexCoordsArray;\
- uniform highp mat4 pmvMatrix;\
+ attribute highp vec2 vertexCoordsArray;\
+ uniform highp mat3 pmvMatrix;\
void setPosition(void)\
{\
- gl_Position = pmvMatrix * vertexCoordsArray;\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \
+ gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \
}";
static const char* const qglslUntransformedPositionVertexShader = "\
@@ -116,20 +119,19 @@ static const char* const qglslUntransformedPositionVertexShader = "\
// 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; \
+ 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) { \
- gl_Position = pmvMatrix * vertexCoordsArray;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ 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 vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \
}";
@@ -147,20 +149,19 @@ static const char* const qglslPatternBrushSrcFragmentShader = "\
// Linear Gradient Brush
static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\
- attribute highp vec4 vertexCoordsArray; \
- uniform highp mat4 pmvMatrix; \
+ 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() { \
- gl_Position = pmvMatrix * vertexCoordsArray;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ 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.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \
}";
@@ -178,20 +179,19 @@ static const char* const qglslLinearGradientBrushSrcFragmentShader = "\
// Conical Gradient Brush
static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\
- attribute highp vec4 vertexCoordsArray;\
- uniform highp mat4 pmvMatrix;\
+ attribute highp vec2 vertexCoordsArray;\
+ uniform highp mat3 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; \
+ 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.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
A = hTexCoords.xy * invertedHTexCoordsZ; \
}";
@@ -215,8 +215,8 @@ static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\
// Radial Gradient Brush
static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\
- attribute highp vec4 vertexCoordsArray;\
- uniform highp mat4 pmvMatrix;\
+ attribute highp vec2 vertexCoordsArray;\
+ uniform highp mat3 pmvMatrix;\
uniform mediump vec2 halfViewportSize; \
uniform highp mat3 brushTransform; \
uniform highp vec2 fmp; \
@@ -224,13 +224,12 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\
varying highp vec2 A; \
void setPosition(void) \
{\
- gl_Position = pmvMatrix * vertexCoordsArray;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ 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.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
A = hTexCoords.xy * invertedHTexCoordsZ; \
b = 2.0 * dot(A, fmp); \
}";
@@ -253,20 +252,19 @@ static const char* const qglslRadialGradientBrushSrcFragmentShader = "\
// Texture Brush
static const char* const qglslPositionWithTextureBrushVertexShader = "\
- attribute highp vec4 vertexCoordsArray; \
- uniform highp mat4 pmvMatrix; \
+ 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) { \
- gl_Position = pmvMatrix * vertexCoordsArray;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ 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.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \
textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \
}";
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 8ca2fd4..f52ed92 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -583,37 +583,37 @@ void QGL2PaintEngineExPrivate::updateMatrix()
{
// qDebug("QGL2PaintEngineExPrivate::updateMatrix()");
- // We set up the 4x4 transformation matrix on the vertex shaders to
- // be the equivalent of glOrtho(0, w, h, 0, -1, 1) * transform:
- //
- // | 2/width 0 0 -1 | | m11 m21 0 dx |
- // | 0 -2/height 0 1 | | m12 m22 0 dy |
- // | 0 0 -1 0 | * | 0 0 1 0 |
- // | 0 0 0 1 | | m13 m23 0 m33 |
- //
- // We expand out the multiplication to save the cost of a full 4x4
- // matrix multiplication as most of the components are trivial.
const QTransform& transform = q->state()->matrix;
- qreal wfactor = 2.0 / width;
- qreal hfactor = -2.0 / height;
-
- pmvMatrix[0][0] = wfactor * transform.m11() - transform.m13();
- pmvMatrix[0][1] = hfactor * transform.m12() + transform.m13();
- pmvMatrix[0][2] = 0.0;
- pmvMatrix[0][3] = transform.m13();
- pmvMatrix[1][0] = wfactor * transform.m21() - transform.m23();
- pmvMatrix[1][1] = hfactor * transform.m22() + transform.m23();
- pmvMatrix[1][2] = 0.0;
- pmvMatrix[1][3] = transform.m23();
- pmvMatrix[2][0] = 0.0;
- pmvMatrix[2][1] = 0.0;
- pmvMatrix[2][2] = -1.0;
- pmvMatrix[2][3] = 0.0;
- pmvMatrix[3][0] = wfactor * transform.dx() - transform.m33();
- pmvMatrix[3][1] = hfactor * transform.dy() + transform.m33();
- pmvMatrix[3][2] = 0.0;
- pmvMatrix[3][3] = transform.m33();
+ // The projection matrix converts from Qt's coordinate system to GL's coordinate system
+ // * GL's viewport is 2x2, Qt's is width x height
+ // * GL has +y -> -y going from bottom -> top, Qt is the other way round
+ // * GL has [0,0] in the center, Qt has it in the top-left
+ //
+ // This results in the Projection matrix below, which is multiplied by the painter's
+ // transformation matrix, as shown below:
+ //
+ // Projection Matrix Painter Transform
+ // ------------------------------------------------ ------------------------
+ // | 2.0 / width | 0.0 | -1.0 | | m11 | m21 | dx |
+ // | 0.0 | -2.0 / height | 1.0 | * | m12 | m22 | dy |
+ // | 0.0 | 0.0 | 1.0 | | m13 | m23 | m33 |
+ // ------------------------------------------------ ------------------------
+ //
+ // NOTE: The resultant matrix is also transposed, as GL expects column-major matracies
+
+ const GLfloat wfactor = 2.0f / width;
+ const GLfloat hfactor = -2.0f / height;
+
+ pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13();
+ pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23();
+ pmvMatrix[2][0] = (wfactor * transform.dx() ) - transform.m33();
+ pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13();
+ pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23();
+ pmvMatrix[2][1] = (hfactor * transform.dy() ) + transform.m33();
+ pmvMatrix[0][2] = transform.m13();
+ pmvMatrix[1][2] = transform.m23();
+ pmvMatrix[2][2] = transform.m33();
// 1/10000 == 0.0001, so we have good enough res to cover curves
// that span the entire widget...
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 33ce24d..f1ec6e6 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -254,7 +254,7 @@ public:
GLfloat staticVertexCoordinateArray[8];
GLfloat staticTextureCoordinateArray[8];
- GLfloat pmvMatrix[4][4];
+ GLfloat pmvMatrix[3][3];
QGLEngineShaderManager* shaderManager;