[cairo] [patch] gl/msaa: upload image inplace instead of creating extra scratch gl surface
Henry (Yu) Song - SISA
hsong at sisa.samsung.com
Tue Jan 29 09:19:53 PST 2013
>From 1b95f6946f028988e6905060aa5ee037ab52990f Mon Sep 17 00:00:00 2001
From: Henry Song <henry.song at samsung.com>
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
More information about the cairo
mailing list