[patch] gl/msaa: upload image inplace instead of creating extra scratch gl surface
"Henry (Yu) Song - SISA" <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <3955FA337689574EB32F94B12A7E6E9E434AC781@sisaex01sj> |
From 1b95f6946f028988e6905060aa5ee037ab52990f Mon Sep 17 00:00:00 2001 From: Henry Song <[email protected]> Date: Tue, 29 Jan 2013 09:15:46 -0800 Subject: [PATCH] gl/msaa: upload image inplace in paint if the source pattern is an image and pattern is pixel-aligned without scale and rotation. This saves GPU memory without creating extra scratch surface --- src/cairo-gl-msaa-compositor.c | 117 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c index 54772ef..b9ffd8f 100644 --- a/src/cairo-gl-msaa-compositor.c +++ b/src/cairo-gl-msaa-compositor.c @@ -47,6 +47,8 @@ #include "cairo-gl-private.h" #include "cairo-path-private.h" #include "cairo-traps-private.h" +#include "cairo-image-surface-private.h" +#include "cairo-surface-offset-private.h" static cairo_bool_t can_use_msaa_compositor (cairo_gl_surface_t *surface, @@ -213,6 +215,112 @@ _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx, } static cairo_bool_t +_pattern_is_pixel_aligned (const cairo_pattern_t *pattern) +{ + return pattern->matrix.xx == 1 && + pattern->matrix.yy == 1 && + pattern->matrix.xy == 0 && + pattern->matrix.yx == 0 && + ceil (pattern->matrix.x0) == pattern->matrix.x0 && + ceil (pattern->matrix.y0) == pattern->matrix.y0; +} + +static cairo_bool_t +_pattern_is_image_surface (const cairo_pattern_t *pattern) +{ + cairo_surface_t *surface; + + if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE) + return FALSE; + + surface = ((cairo_surface_pattern_t *)pattern)->surface; + return surface->type == CAIRO_SURFACE_TYPE_IMAGE; +} + +static cairo_int_status_t +_cairo_gl_msaa_compositor_upload_image_inplace (const cairo_compositor_t *compositor, + cairo_composite_rectangles_t *composite) +{ + cairo_image_surface_t *image, *rgba_image = NULL; + cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + cairo_gl_context_t *ctx; + cairo_gl_dispatch_t *dispatch; + pixman_format_code_t pixman_format; + + const cairo_pattern_t *pattern = composite->original_source_pattern; + cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; + + if (_pattern_is_image_surface (pattern) && + _pattern_is_pixel_aligned (pattern) && + cairo_pattern_get_extend ((cairo_pattern_t *)pattern) == CAIRO_EXTEND_NONE && + _cairo_gl_surface_is_texture (dst)) { + if ((dst->base.is_clear && + (composite->op == CAIRO_OPERATOR_OVER || + composite->op == CAIRO_OPERATOR_ADD)) || + composite->op == CAIRO_OPERATOR_SOURCE) { + status = _cairo_gl_context_acquire (dst->base.device, &ctx); + if (unlikely (status)) + return status; + + dispatch = &ctx->dispatch; + + image = (cairo_image_surface_t *) + cairo_surface_map_to_image (&dst->base, &composite->bounded); + + /* GLES2 core profile only supports RGBA/RGB/ALPHA, we need + * to convert to RGBA if mapped image is not right format + */ + pixman_format = _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8; + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && + image->pixman_format != pixman_format) { + rgba_image = (cairo_image_surface_t *) + _cairo_image_surface_create_with_pixman_format (NULL, + pixman_format, + composite->bounded.width, + composite->bounded.height, + 0); + /* dst is either clear or we have right operator, so + * we don't need to paint image to rgba_image + */ + rgba_image->base.device_transform = image->base.device_transform; + rgba_image->base.device_transform_inverse = image->base.device_transform_inverse; + cairo_surface_destroy (&image->base); + image = rgba_image; + } + + status = _cairo_surface_offset_paint (&image->base, + composite->bounded.x, + composite->bounded.y, + CAIRO_OPERATOR_SOURCE, + pattern, + NULL); + if (unlikely (status)) { + cairo_surface_destroy (&image->base); + status = _cairo_gl_context_release (ctx, status); + return status; + } + + /* ensure we are bind to the current FB) and multisample + * buffer has been resolved + */ + _cairo_gl_context_set_destination (ctx, dst, FALSE); + dispatch->BindFramebuffer (GL_FRAMEBUFFER, 0); + + /* reset surface->parent, otherwise, unmap_image + * calls backend paint again, which causes recursion + */ + image->parent = NULL; + cairo_surface_unmap_image (&dst->base, &image->base); + dispatch->BindFramebuffer (GL_FRAMEBUFFER, dst->fb); + + status = _cairo_gl_context_release (ctx, status); + } + } + + return status; +} + +static cairo_bool_t _should_use_unbounded_surface (cairo_composite_rectangles_t *composite) { cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; @@ -501,7 +609,14 @@ static cairo_int_status_t _cairo_gl_msaa_compositor_paint (const cairo_compositor_t *compositor, cairo_composite_rectangles_t *composite) { - return _cairo_gl_msaa_compositor_mask (compositor, composite); + cairo_int_status_t status = + _cairo_gl_msaa_compositor_upload_image_inplace (compositor, + composite); + + if (status == CAIRO_INT_STATUS_UNSUPPORTED) + return _cairo_gl_msaa_compositor_mask (compositor, composite); + + return status; } static cairo_status_t -- 1.7.9.5 -- cairo mailing list [email protected] http://lists.cairographics.org/mailman/listinfo/cairo