summaryrefslogtreecommitdiff
path: root/src/cairo-gl-surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-gl-surface.c')
-rw-r--r--src/cairo-gl-surface.c73
1 files changed, 59 insertions, 14 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 8ecc3a92e..6be6d9868 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -395,6 +395,7 @@ _cairo_gl_surface_init (cairo_device_t *device,
surface->width = width;
surface->height = height;
surface->needs_update = FALSE;
+ surface->content_in_texture = FALSE;
_cairo_gl_surface_embedded_operand_init (surface);
}
@@ -433,6 +434,7 @@ _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx,
_cairo_gl_surface_init (&ctx->base, surface, content, width, height);
surface->supports_msaa = ctx->supports_msaa;
+ surface->num_samples = ctx->num_samples;
surface->supports_stencil = TRUE;
/* Create the texture used to store the surface's data. */
@@ -875,7 +877,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
if (unlikely (status))
return status;
- if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) {
+ if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 ||
+ _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) {
pixman_format_code_t pixman_format;
cairo_surface_pattern_t pattern;
cairo_bool_t require_conversion = FALSE;
@@ -885,13 +888,12 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
if (src->pixman_format != pixman_format)
require_conversion = TRUE;
}
- else if (dst->base.content != CAIRO_CONTENT_ALPHA)
+ else if (dst->base.content != CAIRO_CONTENT_ALPHA) {
+ require_conversion = TRUE;
+ }
+ else if (src->pixman_format != PIXMAN_a8) {
+ pixman_format = PIXMAN_a8;
require_conversion = TRUE;
- else {
- if (src->pixman_format == PIXMAN_a1) {
- pixman_format = PIXMAN_a8;
- require_conversion = TRUE;
- }
}
if (require_conversion) {
@@ -980,10 +982,19 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
else
{
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
}
+ /* we must resolve the renderbuffer to texture before we
+ upload image */
+ status = _cairo_gl_surface_resolve_multisampling (dst);
+ if (unlikely (status)) {
+ free (data_start_gles2);
+ goto FAIL;
+ }
+
_cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
glBindTexture (ctx->tex_target, dst->tex);
glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -1003,6 +1014,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
dst_x, dst_y,
width, height);
}
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ dst->content_in_texture = TRUE;
} else {
cairo_surface_t *tmp;
@@ -1042,6 +1055,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
}
cairo_surface_destroy (tmp);
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ dst->content_in_texture = TRUE;
}
FAIL:
@@ -1092,7 +1107,7 @@ _cairo_gl_surface_finish (void *abstract_surface)
if (surface->msaa_depth_stencil)
ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
-#if CAIRO_HAS_GL_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
if (surface->msaa_fb)
ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
if (surface->msaa_rb)
@@ -1144,7 +1159,8 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
return NULL;
}
- if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) {
+ if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3 ||
+ _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) {
/* 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
@@ -1193,13 +1209,29 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
* fall back instead.
*/
_cairo_gl_composite_flush (ctx);
- _cairo_gl_context_set_destination (ctx, surface, FALSE);
+
+ if (ctx->gl_flavor != CAIRO_GL_FLAVOR_ES3) {
+ _cairo_gl_context_set_destination (ctx, surface, FALSE);
+ } else {
+ if (surface->content_in_texture) {
+ _cairo_gl_ensure_framebuffer (ctx, surface);
+ ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
+ } else {
+ status = _cairo_gl_surface_resolve_multisampling (surface);
+ if (unlikely (status)) {
+ status = _cairo_gl_context_release (ctx, status);
+ cairo_surface_destroy (&image->base);
+ return _cairo_image_surface_create_in_error (status);
+ }
+ }
+ }
flipped = ! _cairo_gl_surface_is_texture (surface);
mesa_invert = flipped && ctx->has_mesa_pack_invert;
glPixelStorei (GL_PACK_ALIGNMENT, 4);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
if (mesa_invert)
glPixelStorei (GL_PACK_INVERT_MESA, 1);
@@ -1366,6 +1398,9 @@ _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
/* GLES surfaces do not need explicit resolution. */
if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2)
return CAIRO_INT_STATUS_SUCCESS;
+ else if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES3 &&
+ surface->content_in_texture)
+ return CAIRO_INT_STATUS_SUCCESS;
if (! _cairo_gl_surface_is_texture (surface))
return CAIRO_INT_STATUS_SUCCESS;
@@ -1374,10 +1409,20 @@ _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
if (unlikely (status))
return status;
- ctx->current_target = surface;
+#if CAIRO_HAS_GLESV3_SURFACE
+ _cairo_gl_composite_flush (ctx);
+ ctx->current_target = NULL;
+ _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ surface->content_in_texture = TRUE;
-#if CAIRO_HAS_GL_SURFACE
+#elif CAIRO_HAS_GL_SURFACE
+ ctx->current_target = surface;
_cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
+
+#else
+ ctx->current_target = surface;
+
#endif
status = _cairo_gl_context_release (ctx, status);