[cairo] [PATCH 34/39] [OpenVG] reuse paint object, have a cache of images
tardyp at gmail.com
tardyp at gmail.com
Fri Jul 10 10:02:36 PDT 2009
From: Øyvind Kolås <pippin at gimp.org>
Patch based on initial hack for reusing cairo_image_t's
-------
Hi!
Attached is the patch from the current repository HEAD to caching
persistent images plus the paint reusability optimization. With the
latest ShivaVG source it should restore the previous performace while
still supporting additional formats. Here's a brief comment of
changes:
* cairo_openvg_setup_solid_source: PAINT_TYPE is re-set to PAINT_TYPE_COLOR
* cairo_openvg_setup_surface_source: doesn't rearrange the data in a
temp buffer but passes it to openvg directly using ARGB format. I'm
not sure if thats supported by AmanithVG, so I just commented it out.
It does work with ShivaVG perfectly, though.
* setup_source: removed the check for non-destructed paint
* teardown_source: removed paint destruction code
* added _cairo_openvg_surface_finish to destroy the reusable paint object
* cairo_openvg_surface_create: creates the reusable paint object
cheers,
Ivan
---
src/cairo-openvg-surface.c | 95 +++++++++++++++++++++++++++++++++++---------
1 files changed, 76 insertions(+), 19 deletions(-)
diff --git a/src/cairo-openvg-surface.c b/src/cairo-openvg-surface.c
index 2782646..bed9902 100644
--- a/src/cairo-openvg-surface.c
+++ b/src/cairo-openvg-surface.c
@@ -39,6 +39,14 @@
#define MAX_OPACITIES 32
+typedef struct cached_image_t {
+ VGImage vg_image; /*< set to 0 when entry not used */
+ void *cairo_image;
+ void *data;
+} cached_image_t;
+
+#define MAX_IMAGES 32
+
typedef struct cairo_openvg_surface {
cairo_surface_t base;
cairo_content_t content;
@@ -51,6 +59,8 @@ typedef struct cairo_openvg_surface {
double alpha;
double opacity[MAX_OPACITIES];
int opacity_level;
+
+ cached_image_t images[MAX_IMAGES];
} cairo_openvg_surface_t;
static void
@@ -477,6 +487,8 @@ _cairo_openvg_setup_solid_source (cairo_openvg_surface_t *vgsurface,
spat->color.green,
spat->color.blue,
spat->color.alpha * vgsurface->alpha};
+
+ vgSetParameteri(vgsurface->source_paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv (vgsurface->source_paint, VG_PAINT_COLOR, 4, color);
return CAIRO_STATUS_SUCCESS;
}
@@ -505,19 +517,60 @@ _cairo_openvg_setup_surface_source (cairo_openvg_surface_t *vgsurface,
image->format == CAIRO_FORMAT_A8 ||
image->format == CAIRO_FORMAT_A1);
+
+ {
+ int i;
+ for (i=0; i<MAX_IMAGES;i++)
+ {
+ if (vgsurface->images[i].vg_image &&
+ (vgsurface->images[i].cairo_image == image ||
+ vgsurface->images[i].data == image->data))
+ {
+ vgsurface->source_image = vgsurface->images[i].vg_image;
+ /*fprintf (stderr, "found in cache!\n");*/
+ goto USED_CACHE;
+ }
+ }
+ }
+
vgsurface->source_image = vgCreateImage (VG_sRGBA_8888,
image->width, image->height, VG_IMAGE_QUALITY_FASTER);
/* NONALIASED, FASTER, BETTER */
- /*printf ("image: %ix%i\n", image->width, image->height);*/
- data = malloc (image->width * image->height * 4);
+ { /* store in cache */
+ int i;
+ int done = 0;
+ for (i=0; i<MAX_IMAGES;i++)
+ {
+ if (vgsurface->images[i].vg_image == 0)
+ {
+ vgsurface->images[i].vg_image = vgsurface->source_image;
+ vgsurface->images[i].cairo_image = image;
+ vgsurface->images[i].data = image->data;
+ done = 1;
+ break;
+ }
+ }
+ if (done == 0)
+ {
+ i=1;
+ vgDestroyImage (vgsurface->images[i].vg_image);
+ vgsurface->images[i].vg_image = vgsurface->source_image;
+ vgsurface->images[i].cairo_image = image;
+ vgsurface->images[i].data = image->data;
+ }
+ }
+
+ printf ("image: %p %p %ix%i\n", image, image->data, image->width, image->height);
+
+ /*data = malloc (image->width * image->height * 4);*/
/* This extra allocation and copy/conversion should not be neccesary if the
* OpenVG implementation supports the pixelformats in the specification, at
* the moment it doesn't seem like neither ShivaVG nor AmantihVG does so
* however.
- */
+ */ /*
{
int i;
for (i=0; i<image->width * image->height; i++)
@@ -527,12 +580,14 @@ _cairo_openvg_setup_surface_source (cairo_openvg_surface_t *vgsurface,
data[4*i+2] = image->data[4*i+0];
data[4*i+3] = image->data[4*i+3];
}
- }
+ } */
+
+ vgImageSubData (vgsurface->source_image, image->data, image->width*4,
+ VG_sARGB_8888, 0, 0, image->width, image->height);
- vgImageSubData (vgsurface->source_image, data, image->width*4,
- VG_sRGBA_8888, 0, 0, image->width, image->height);
+ /*free (data);*/
- free (data);
+USED_CACHE:
vgSetParameteri (vgsurface->source_paint,
VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
@@ -580,11 +635,9 @@ setup_source (cairo_openvg_surface_t *vgsurface,
/* this will bomb if one of the prior paint ops have failed to
* clean up after itself
*/
-
- assert (vgsurface->source_paint == 0);
+
assert (vgsurface->source_image == 0);
-
- vgsurface->source_paint = vgCreatePaint();
+
if (source->type == CAIRO_PATTERN_TYPE_SOLID)
{
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
@@ -616,14 +669,9 @@ static cairo_status_t
teardown_source (cairo_openvg_surface_t *vgsurface,
cairo_pattern_t *source)
{
- if (vgsurface->source_paint)
- {
- vgDestroyPaint (vgsurface->source_paint);
- vgsurface->source_paint = 0;
- }
if (vgsurface->source_image)
{
- vgDestroyImage (vgsurface->source_image);
+ /*vgDestroyImage (vgsurface->source_image);*/
vgsurface->source_image = 0;
}
return CAIRO_STATUS_SUCCESS;
@@ -714,7 +762,7 @@ _cairo_openvg_surface_fill (void *asurface,
rv = setup_source (vgsurface, source);
if (rv)
goto BAIL;
-
+
vgSetPaint(vgsurface->source_paint, VG_FILL_PATH);
vgDrawPath (vg_path.path, VG_FILL_PATH);
vgDestroyPath (vg_path.path);
@@ -881,11 +929,19 @@ _cairo_openvg_surface_show_glyphs (void *asurface,
return status;
}
+static cairo_status_t
+_cairo_openvg_surface_finish (void *abstract_surface)
+{
+ cairo_openvg_surface_t *vgsurface = (cairo_openvg_surface_t*) abstract_surface;
+ if (vgsurface->source_paint != VG_INVALID_HANDLE)
+ vgDestroyPaint (vgsurface->source_paint);
+}
+
static const struct _cairo_surface_backend
cairo_openvg_surface_backend = {
CAIRO_SURFACE_TYPE_OPENVG,
_cairo_openvg_surface_create_similar,
- NULL, /* finish */
+ _cairo_openvg_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
@@ -929,6 +985,7 @@ cairo_openvg_surface_create (int width, int height)
s->alpha = 1.0;
s->opacity_level = 0;
s->opacity[s->opacity_level] = 1.0;
+ s->source_paint = vgCreatePaint();
vgLoadIdentity();
/* The default transform of cairo and OpenVG differ, (cairo has the
--
1.6.0.4
More information about the cairo
mailing list