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

"Henry (Yu) Song - SISA" <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <3955FA337689574EB32F94B12A7E6E9E434BC80B@sisaex01sj>
re-post patch, please review
________________________________________
From: Henry (Yu) Song - SISA
Sent: Friday, February 01, 2013 2:09 PM
To: [email protected]
Subject: [patch 1/2] gl: create BGRA texture if driver supports

From 9ed43276f513c0e818948227029b739faf22c4e0 Mon Sep 17 00:00:00 2001
From: Henry Song <[email protected]>
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
-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.