[09/21] gl: Require the GL_EXT_texture_format_BGRA8888 extension for GLES2

Message ID 1311602208-5973-9-git-send-email-alexandros.frantzis@linaro.org
State Accepted
Headers show

Commit Message

alexandros.frantzis@linaro.org July 25, 2011, 1:56 p.m.
From: Alexandros Frantzis <alexandros.frantzis@linaro.org>

This extension adds limited BGRA support to GLES2. It is better than
nothing...

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 src/cairo-gl-device.c          |    7 ++++++-
 src/cairo-gl-ext-def-private.h |   12 ++++++++++++
 src/cairo-gl-gradient.c        |   23 ++++++++++++++++++++---
 3 files changed, 38 insertions(+), 4 deletions(-)

Patch

diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 35339aa..ca7b6e8 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -156,6 +156,7 @@  _cairo_gl_context_init (cairo_gl_context_t *ctx)
     cairo_status_t status;
     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
     int gl_version = _cairo_gl_get_version ();
+    cairo_gl_flavor_t gl_flavor = _cairo_gl_get_flavor ();
     int n;
 
     _cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
@@ -179,11 +180,15 @@  _cairo_gl_context_init (cairo_gl_context_t *ctx)
 	! _cairo_gl_has_extension ("GL_ARB_pixel_buffer_object"))
 	return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
 
+    if (gl_flavor == CAIRO_GL_FLAVOR_ES &&
+	! _cairo_gl_has_extension ("GL_EXT_texture_format_BGRA8888"))
+	return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
+
     ctx->has_mesa_pack_invert =
 	_cairo_gl_has_extension ("GL_MESA_pack_invert");
 
     ctx->current_operator = -1;
-    ctx->gl_flavor = _cairo_gl_get_flavor ();
+    ctx->gl_flavor = gl_flavor;
 
     status = _cairo_gl_context_init_shaders (ctx);
     if (unlikely (status))
diff --git a/src/cairo-gl-ext-def-private.h b/src/cairo-gl-ext-def-private.h
index 389d356..0701c5b 100644
--- a/src/cairo-gl-ext-def-private.h
+++ b/src/cairo-gl-ext-def-private.h
@@ -100,4 +100,16 @@ 
 #define GL_CLAMP_TO_BORDER 0x812D
 #endif
 
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+
+#ifndef GL_RGBA8
+#define GL_RGBA8 0x8058
+#endif
+
+#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+
 #endif /* CAIRO_GL_EXT_DEF_PRIVATE_H */
diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index ef7fd53..0718c75 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -44,6 +44,7 @@ 
 #include "cairo-gl-gradient-private.h"
 #include "cairo-gl-private.h"
 
+
 static int
 _cairo_gl_gradient_sample_width (unsigned int                 n_stops,
                                  const cairo_gradient_stop_t *stops)
@@ -95,6 +96,17 @@  _cairo_gl_gradient_render (const cairo_gl_context_t    *ctx,
     pixman_gradient_stop_t *pixman_stops;
     pixman_point_fixed_t p1, p2;
     unsigned int i;
+    pixman_format_code_t gradient_pixman_format;
+
+    /*
+     * Ensure that the order of the gradient's components in memory is BGRA.
+     * This is done so that the gradient's pixel data is always suitable for
+     * texture upload using format=GL_BGRA and type=GL_UNSIGNED_BYTE.
+     */
+    if (_cairo_is_little_endian ())
+	gradient_pixman_format = PIXMAN_a8r8g8b8;
+    else
+	gradient_pixman_format = PIXMAN_b8g8r8a8;
 
     pixman_stops = pixman_stops_stack;
     if (unlikely (n_stops > ARRAY_LENGTH (pixman_stops_stack))) {
@@ -129,7 +141,7 @@  _cairo_gl_gradient_render (const cairo_gl_context_t    *ctx,
     pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
     pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
 
-    image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1,
+    image = pixman_image_create_bits (gradient_pixman_format, width, 1,
 				      bytes, sizeof(uint32_t)*width);
     if (unlikely (image == NULL)) {
 	pixman_image_unref (gradient);
@@ -240,8 +252,13 @@  _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
     glGenTextures (1, &gradient->tex);
     _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
     glBindTexture (ctx->tex_target, gradient->tex);
-    glTexImage2D (ctx->tex_target, 0, GL_RGBA8, tex_width, 1, 0,
-		  GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+
+    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+	glTexImage2D (ctx->tex_target, 0, GL_RGBA8, tex_width, 1, 0,
+		      GL_BGRA, GL_UNSIGNED_BYTE, 0);
+    else
+	glTexImage2D (ctx->tex_target, 0, GL_BGRA, tex_width, 1, 0,
+		      GL_BGRA, GL_UNSIGNED_BYTE, data);
 
     dispatch->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);