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