[4/6] gl: Use a custom shader uniform for the ModelViewProjection matrix

Message ID 1297163415-31035-5-git-send-email-alexandros.frantzis@linaro.org
State Accepted
Commit 80a92b6d799900057ac40c0c0bb63be48eece9ef
Headers show

Commit Message

alexandros.frantzis@linaro.org Feb. 8, 2011, 11:10 a.m.
From: Alexandros Frantzis <alexandros.frantzis@linaro.org>

The built-in gl_ModelViewProjectionMatrix uniform (and others) has been
deprecated and removed in recent GLSL versions and is not supported
at all in GLSL ES. A custom uniform for the same purpose works across
all versions.
---
 src/cairo-gl-composite.c |    2 +
 src/cairo-gl-device.c    |   53 +++++++++++++++++++++++++++++++++++++++------
 src/cairo-gl-private.h   |    1 +
 src/cairo-gl-shaders.c   |    3 +-
 4 files changed, 51 insertions(+), 8 deletions(-)

Patch

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index a32e00d..7cbe894 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -414,6 +414,8 @@  static void
 _cairo_gl_composite_bind_to_shader (cairo_gl_context_t   *ctx,
 				    cairo_gl_composite_t *setup)
 {
+    _cairo_gl_shader_bind_matrix4f(ctx, "ModelViewProjectionMatrix",
+				   ctx->modelviewprojection_matrix);
     _cairo_gl_operand_bind_to_shader (ctx, &setup->src,  CAIRO_GL_TEX_SOURCE);
     _cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK);
 }
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 25423e0..32543ce 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -269,6 +269,48 @@  _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
     }
 }
 
+/*
+ * Stores a parallel projection transformation in matrix 'm',
+ * using column-major order.
+ *
+ * This is equivalent to:
+ *
+ * glLoadIdentity()
+ * glOrtho()
+ *
+ * The calculation for the ortho tranformation was taken from the
+ * mesa source code.
+ */
+static void
+_gl_identity_ortho (GLfloat left, GLfloat right,
+		    GLfloat bottom, GLfloat top,
+		    GLfloat nearval, GLfloat farval,
+		    GLfloat *m)
+{
+#define M(row,col)  m[col*4+row]
+    M(0,0) = 2.0F / (right - left);
+    M(0,1) = 0.0F;
+    M(0,2) = 0.0F;
+    M(0,3) = -(right + left) / (right - left);
+
+    M(1,0) = 0.0F;
+    M(1,1) = 2.0F / (top - bottom);
+    M(1,2) = 0.0F;
+    M(1,3) = -(top + bottom) / (top - bottom);
+
+    M(2,0) = 0.0F;
+    M(2,1) = 0.0F;
+    M(2,2) = -2.0F / (farval - nearval);
+    M(2,3) = -(farval + nearval) / (farval - nearval);
+
+    M(3,0) = 0.0F;
+    M(3,1) = 0.0F;
+    M(3,2) = 0.0F;
+    M(3,3) = 1.0F;
+#undef M
+}
+
+
 void
 _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
                                    cairo_gl_surface_t *surface)
@@ -295,13 +337,10 @@  _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
 
     glViewport (0, 0, surface->width, surface->height);
 
-    glMatrixMode (GL_PROJECTION);
-    glLoadIdentity ();
     if (_cairo_gl_surface_is_texture (surface))
-	glOrtho (0, surface->width, 0, surface->height, -1.0, 1.0);
+	_gl_identity_ortho (0, surface->width, 0, surface->height, -1.0, 1.0,
+			    ctx->modelviewprojection_matrix);
     else
-	glOrtho (0, surface->width, surface->height, 0, -1.0, 1.0);
-
-    glMatrixMode (GL_MODELVIEW);
-    glLoadIdentity ();
+	_gl_identity_ortho (0, surface->width, surface->height, 0, -1.0, 1.0,
+			    ctx->modelviewprojection_matrix);
 }
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 3dd75f8..61c382d 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -259,6 +259,7 @@  struct _cairo_gl_context {
 
     cairo_bool_t has_mesa_pack_invert;
     cairo_gl_dispatch_t dispatch;
+    GLfloat modelviewprojection_matrix[16];
 
     void (*acquire) (void *ctx);
     void (*release) (void *ctx);
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 13efccb..6a3a606 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -518,9 +518,10 @@  cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
     cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_TEX_MASK);
 
     _cairo_output_stream_printf (stream,
+				 "uniform mat4 ModelViewProjectionMatrix;\n"
 				 "void main()\n"
 				 "{\n"
-				 "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n");
+				 "    gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n");
 
     cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_TEX_SOURCE);
     cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_TEX_MASK);