diff options
Diffstat (limited to 'src/cairo-gl-surface.c')
-rw-r--r-- | src/cairo-gl-surface.c | 73 |
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); |