mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-06-16 22:38:30 +02:00
gl: Add BGRA download support for GLES2
Some OpenGLES2 drivers support downloading BGRA data. On little-endian systems BGRA and GL_UNSIGNED_BYTe is equivalent to the typical cairo_image_t format, so this can prevent CPU bit swizzling for operations that involve images.
This commit is contained in:
parent
a7d684e6fe
commit
9d9aa04b60
3 changed files with 44 additions and 26 deletions
|
|
@ -169,6 +169,22 @@ _cairo_gl_msaa_compositor_enabled (void)
|
|||
return env && strcmp(env, "msaa") == 0;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
test_can_read_bgra (cairo_gl_flavor_t gl_flavor)
|
||||
{
|
||||
/* Desktop GL always supports BGRA formats. */
|
||||
if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
|
||||
return TRUE;
|
||||
|
||||
assert (gl_flavor == CAIRO_GL_FLAVOR_ES);
|
||||
|
||||
/* For OpenGL ES we have to look for the specific extension and BGRA only
|
||||
* matches cairo's integer packed bytes on little-endian machines. */
|
||||
if (!_cairo_is_little_endian())
|
||||
return FALSE;
|
||||
return _cairo_gl_has_extension ("EXT_read_format_bgra");
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gl_context_init (cairo_gl_context_t *ctx)
|
||||
{
|
||||
|
|
@ -230,6 +246,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
|
|||
(gl_flavor == CAIRO_GL_FLAVOR_ES &&
|
||||
_cairo_gl_has_extension ("GL_OES_mapbuffer")));
|
||||
|
||||
ctx->can_read_bgra = test_can_read_bgra (gl_flavor);
|
||||
|
||||
ctx->has_mesa_pack_invert =
|
||||
_cairo_gl_has_extension ("GL_MESA_pack_invert");
|
||||
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@ struct _cairo_gl_context {
|
|||
cairo_bool_t has_map_buffer;
|
||||
cairo_bool_t has_packed_depth_stencil;
|
||||
cairo_bool_t has_npot_repeat;
|
||||
cairo_bool_t can_read_bgra;
|
||||
|
||||
cairo_bool_t thread_aware;
|
||||
|
||||
|
|
|
|||
|
|
@ -1022,6 +1022,11 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
|
|||
cairo_status_t status;
|
||||
int y;
|
||||
|
||||
status = _cairo_gl_context_acquire (surface->base.device, &ctx);
|
||||
if (unlikely (status)) {
|
||||
return _cairo_image_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
/* Want to use a switch statement here but the compiler gets whiny. */
|
||||
if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
|
||||
format = GL_BGRA;
|
||||
|
|
@ -1043,25 +1048,26 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* GLES2 supports only RGBA, UNSIGNED_BYTE so use that.
|
||||
* We are also using this format for ALPHA as GLES2 does not
|
||||
* support GL_PACK_ROW_LENGTH anyway, and this makes sure that the
|
||||
* pixman image that is created has row_stride = row_width * bpp.
|
||||
*/
|
||||
if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES) {
|
||||
format = GL_RGBA;
|
||||
if (! _cairo_is_little_endian ()) {
|
||||
if (surface->base.content == CAIRO_CONTENT_COLOR)
|
||||
pixman_format = PIXMAN_r8g8b8x8;
|
||||
else
|
||||
pixman_format = PIXMAN_r8g8b8a8;
|
||||
} else {
|
||||
if (surface->base.content == CAIRO_CONTENT_COLOR)
|
||||
pixman_format = PIXMAN_x8b8g8r8;
|
||||
else
|
||||
pixman_format = PIXMAN_a8b8g8r8;
|
||||
/* If only RGBA is supported, we must download data in a compatible
|
||||
* format. This means that pixman will convert the data on the CPU when
|
||||
* interacting with other image surfaces. For ALPHA, GLES2 does not
|
||||
* support GL_PACK_ROW_LENGTH anyway, and this makes sure that the
|
||||
* pixman image that is created has row_stride = row_width * bpp. */
|
||||
if (surface->base.content == CAIRO_CONTENT_ALPHA || !ctx->can_read_bgra) {
|
||||
cairo_bool_t little_endian = _cairo_is_little_endian ();
|
||||
format = GL_RGBA;
|
||||
|
||||
if (surface->base.content == CAIRO_CONTENT_COLOR) {
|
||||
pixman_format = little_endian ?
|
||||
PIXMAN_x8b8g8r8 : PIXMAN_r8g8b8x8;
|
||||
} else {
|
||||
pixman_format = little_endian ?
|
||||
PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
|
||||
}
|
||||
}
|
||||
|
||||
/* GLES2 only supports GL_UNSIGNED_BYTE. */
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
cpp = 4;
|
||||
}
|
||||
|
|
@ -1072,16 +1078,9 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
|
|||
extents->width,
|
||||
extents->height,
|
||||
-1);
|
||||
if (unlikely (image->base.status))
|
||||
if (unlikely (image->base.status) || surface->base.serial == 0) {
|
||||
status = _cairo_gl_context_release (ctx, status);
|
||||
return image;
|
||||
|
||||
if (surface->base.serial == 0)
|
||||
return image;
|
||||
|
||||
status = _cairo_gl_context_acquire (surface->base.device, &ctx);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&image->base);
|
||||
return _cairo_image_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue