[cairo] FW: [patch 1/2] gl: create BGRA texture if driver supports

Henry (Yu) Song - SISA hsong at sisa.samsung.com
Thu Feb 14 11:20:42 PST 2013


re-post patch, please review
________________________________________
From: Henry (Yu) Song - SISA
Sent: Friday, February 01, 2013 2:09 PM
To: cairo at cairographics.org
Subject: [patch 1/2] gl: create BGRA texture if driver supports

>From 9ed43276f513c0e818948227029b739faf22c4e0 Mon Sep 17 00:00:00 2001
From: Henry Song <henry.song at samsung.com>
Date: Fri, 1 Feb 2013 11:50:49 -0800
Subject: [PATCH 1/2] gl: Create BGRA texture if driver supports it

GLES2 drivers can create BGRA format texture if the driver supports
GL_EXT_texture_format_BGRA8888.  In addition, GLES2 can also read
BGRA data if the driver supports GL_EXT_read_bgra.  If both extensions
are present, we can create BGRA texture to avoid image conversion
during upload and download. Also add a function that does BGRA to RGBA
conversion during _cairo_gl_surface_draw_image().
---
 src/cairo-gl-private.h          |    2 +
 src/cairo-gl-surface.c          |   92 +++++++++++++++++++++++++++++++++++++--
 src/cairo-gl-traps-compositor.c |   30 -------------
 3 files changed, 90 insertions(+), 34 deletions(-)

diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index a75afa7..fcaf973 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -183,6 +183,8 @@ struct _cairo_gl_surface {
     cairo_bool_t needs_update;

     cairo_region_t *clip_region;
+
+    GLenum texture_format;
 };

 typedef struct cairo_gl_glyph_cache {
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 922f234..73129e3 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -391,6 +391,7 @@ _cairo_gl_surface_init (cairo_device_t *device,
     surface->width = width;
     surface->height = height;
     surface->needs_update = FALSE;
+    surface->texture_format = GL_RGBA;

     _cairo_gl_surface_embedded_operand_init (surface);
 }
@@ -434,6 +435,9 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
     cairo_gl_surface_t *surface;
     GLenum format;
     GLuint tex;
+    cairo_bool_t can_create_bgra_texture =
+       ( ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
+         ctx->can_read_bgra );

     glGenTextures (1, &tex);
     surface = (cairo_gl_surface_t *)
@@ -454,7 +458,11 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
     default:
        ASSERT_NOT_REACHED;
     case CAIRO_CONTENT_COLOR_ALPHA:
-       format = GL_RGBA;
+       /* Create BGRA format if the driver supports that */
+       if (can_create_bgra_texture)
+           format = GL_BGRA;
+       else
+           format = GL_RGBA;
        break;
     case CAIRO_CONTENT_ALPHA:
        /* When using GL_ALPHA, compositing doesn't work properly, but for
@@ -462,8 +470,12 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
         * an issue. */
        if (for_caching)
            format = GL_ALPHA;
-       else
-           format = GL_RGBA;
+       else {
+           if (can_create_bgra_texture)
+               format = GL_BGRA;
+           else
+               format = GL_RGBA;
+       }
        break;
     case CAIRO_CONTENT_COLOR:
        /* GL_RGB is almost what we want here -- sampling 1 alpha when
@@ -474,10 +486,14 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
         * specified.  So, we have to store RGBA, and fill the alpha
         * channel with 1 when blending.
         */
-       format = GL_RGBA;
+       if (can_create_bgra_texture)
+           format = GL_BGRA;
+       else
+           format = GL_RGBA;
        break;
     }

+    surface->texture_format = format;
     glTexImage2D (ctx->tex_target, 0, format, width, height, 0,
                  format, GL_UNSIGNED_BYTE, NULL);

@@ -835,6 +851,58 @@ _cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
     return status;
 }

+static cairo_image_surface_t *
+_cairo_gl_convert_image (cairo_gl_context_t    *ctx,
+                        cairo_gl_surface_t    *dst,
+                        cairo_image_surface_t *src,
+                        int                   *src_x,
+                        int                   *src_y,
+                        int                    width,
+                        int                    height,
+                        GLenum                *format)
+{
+    cairo_image_surface_t *bgra_src;
+    pixman_format_code_t pixman_format;
+    int stride = 4 * width;
+
+    /* There is no need to create BGRA format image if the driver can
+     * read BGRA/BGR data, this includes
+     * 1. GL drivers
+     * 2. GLES 2 drivers support GL_EXT_read_bgra AND the image is
+     *    BGRA/BGR
+     */
+    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+       (ctx->can_read_bgra                  &&
+        (src->format == CAIRO_FORMAT_ARGB32 ||
+         src->format == CAIRO_FORMAT_RGB24)))
+       return (cairo_image_surface_t *) cairo_surface_reference (&src->base);
+
+    /* if we have created the dst as GL_ALPHA and it is created for glyph
+     * cache, we don' need convert */
+    if (src->base.content == CAIRO_CONTENT_ALPHA &&
+       dst->texture_format == GL_ALPHA          &&
+       dst->tex                                 &&
+       dst->owns_tex)
+       return (cairo_image_surface_t *) cairo_surface_reference (&src->base);
+
+    pixman_format = _cairo_is_little_endian () ?
+       PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
+
+    bgra_src = _cairo_image_surface_create_from_image (src,
+                                                      pixman_format,
+                                                      *src_x, *src_y,
+                                                      width, height,
+                                                      stride);
+    if (unlikely (bgra_src->base.status))
+       return bgra_src;
+
+    *src_x = 0;
+    *src_y = 0;
+    *format = GL_RGBA;
+
+    return bgra_src;
+}
+
 cairo_status_t
 _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
                              cairo_image_surface_t *src,
@@ -845,6 +913,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
     GLenum internal_format, format, type;
     cairo_bool_t has_alpha, needs_swap;
     cairo_image_surface_t *clone = NULL;
+    cairo_image_surface_t *converted_src = NULL;
     cairo_gl_context_t *ctx;
     int cpp;
     cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
@@ -880,6 +949,19 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
        src = clone;
     }

+    /* let's make sure the image src is the right format we can upload */
+    converted_src = _cairo_gl_convert_image (ctx, dst, src,
+                                            &src_x, &src_y,
+                                            width, height,
+                                            &format);
+
+    if (unlikely (converted_src->base.status)) {
+       status = converted_src->base.status;
+       goto FAIL;
+    }
+
+    src = converted_src;
+
     cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;

     status = _cairo_gl_surface_flush (&dst->base, 0);
@@ -982,6 +1064,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 FAIL:
     status = _cairo_gl_context_release (ctx, status);

+    cairo_surface_destroy (&converted_src->base);
+
     if (clone)
         cairo_surface_destroy (&clone->base);

diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c
index b6c2333..620b3fd 100644
--- a/src/cairo-gl-traps-compositor.c
+++ b/src/cairo-gl-traps-compositor.c
@@ -302,36 +302,6 @@ traps_to_operand (void *_dst,
        return image->status;
     }

-    /* GLES2 only supports RGB/RGBA when uploading */
-    if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES) {
-       cairo_surface_pattern_t pattern;
-       cairo_surface_t *rgba_image;
-
-       /* XXX perform this fixup inside _cairo_gl_draw_image() */
-
-       rgba_image =
-           _cairo_image_surface_create_with_pixman_format (NULL,
-                                                           _cairo_is_little_endian () ?  PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8,
-                                                           extents->width,
-                                                           extents->height,
-                                                           0);
-       if (unlikely (rgba_image->status))
-           return rgba_image->status;
-
-       _cairo_pattern_init_for_surface (&pattern, image);
-       status = _cairo_surface_paint (rgba_image, CAIRO_OPERATOR_SOURCE,
-                                      &pattern.base, NULL);
-       _cairo_pattern_fini (&pattern.base);
-
-       cairo_surface_destroy (image);
-       image = rgba_image;
-
-       if (unlikely (status)) {
-           cairo_surface_destroy (image);
-           return status;
-       }
-    }
-
     mask = _cairo_surface_create_similar_scratch (_dst,
                                                  CAIRO_CONTENT_COLOR_ALPHA,
                                                  extents->width,
--
1.7.9.5


More information about the cairo mailing list