[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