[cairo-commit] src/cairo-clip.c src/cairo-directfb-surface.c
src/cairo-glitz-surface.c src/cairo-image-surface.c
src/cairoint.h src/cairo-nquartz-surface.c
src/cairo-pattern.c src/cairo-surface.c
src/cairo-xcb-surface.c src/cairo-xlib-surface.c
Carl Worth
cworth at kemper.freedesktop.org
Wed Oct 18 17:06:34 PDT 2006
src/cairo-clip.c | 7 ++++++-
src/cairo-directfb-surface.c | 18 +++++++++++++-----
src/cairo-glitz-surface.c | 30 ++++++++++++++++++++++--------
src/cairo-image-surface.c | 4 ++++
src/cairo-nquartz-surface.c | 9 +++++++--
src/cairo-pattern.c | 38 ++++++++++++++++++++------------------
src/cairo-surface.c | 14 ++++++++++++--
src/cairo-xcb-surface.c | 9 +++++++++
src/cairo-xlib-surface.c | 18 ++++++++++++++----
src/cairoint.h | 8 ++++++++
10 files changed, 115 insertions(+), 40 deletions(-)
New commits:
diff-tree 8d7a02ed58e06584eb09575e6ca11d0a81094ab6 (from 99e2e99a78e492196a76e76cb47e463223db3012)
Author: Christopher (Monty) Montgomery <xiphmont at gmail.com>
Date: Wed Oct 18 17:06:23 2006 -0700
Add extents to clone_similar (fixing subimage_copy performance bug)
This fixes a huge performance bug (entire image was being pushed to X
server in order to copy a tiny piece of it). I see up to 50x improvement
from subimage_copy (which was designed to expose this problem) but also
a 5x improvement in some text performance cases.
xlib-rgba subimage_copy-512 3.93 2.46% -> 0.07 2.71%: 52.91x faster
ââââââââââââââââââââââââââââââââââââââââââââââââââââ
xlib-rgb subimage_copy-512 4.03 1.97% -> 0.09 2.61%: 44.74x faster
ââââââââââââââââââââââââââââââââââââââââââââ
xlib-rgba subimage_copy-256 1.02 2.25% -> 0.07 0.56%: 14.42x faster
ââââââââââââââ
xlib-rgba text_image_rgb_over-256 63.21 1.53% -> 11.87 2.17%: 5.33x faster
âââââ
xlib-rgba text_image_rgba_over-256 62.31 0.72% -> 11.87 2.82%: 5.25x faster
âââââ
xlib-rgba text_image_rgba_source-256 67.97 0.85% -> 16.48 2.23%: 4.13x faster
ââââ
xlib-rgba text_image_rgb_source-256 68.82 0.55% -> 16.93 2.10%: 4.07x faster
ââââ
xlib-rgba subimage_copy-128 0.19 1.72% -> 0.06 0.85%: 3.10x faster
âââ
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 3f7c0c0..516e3b0 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -563,7 +563,12 @@ _cairo_clip_init_deep_copy (cairo_clip_t
}
if (other->surface) {
- _cairo_surface_clone_similar (target, clip->surface, &clip->surface);
+ _cairo_surface_clone_similar (target, clip->surface,
+ clip->surface_rect.x,
+ clip->surface_rect.y,
+ clip->surface_rect.width,
+ clip->surface_rect.height,
+ &clip->surface);
clip->surface_rect = other->surface_rect;
}
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index fdff40a..e724ed6 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -548,6 +548,10 @@ _cairo_directfb_surface_release_dest_ima
static cairo_status_t
_cairo_directfb_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out)
{
cairo_directfb_surface_t *surface = abstract_surface;
@@ -583,19 +587,23 @@ _cairo_directfb_surface_clone_similar (v
cairo_surface_destroy ((cairo_surface_t *)clone);
return CAIRO_STATUS_NO_MEMORY;
}
+
+ dst += pitch * src_y;
+ src += image_src->stride * src_y;
if (image_src->format == CAIRO_FORMAT_A1) {
/* A1 -> A8 */
- for (i = 0; i < image_src->height; i++) {
- for (j = 0; j < image_src->width; j++)
+ for (i = 0; i < height; i++) {
+ for (j = src_x; j < src_x + width; j++)
dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
dst += pitch;
src += image_src->stride;
}
}
- else {
- for (i = 0; i < image_src->height; i++) {
- direct_memcpy( dst, src, image_src->stride );
+ else {
+ /* A8 -> A8 */
+ for (i = 0; i < height; i++) {
+ direct_memcpy( dst+src_x, src+src_x, sizeof(*dst)*width );
dst += pitch;
src += image_src->stride;
}
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 3536619..5310e22 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -244,8 +244,12 @@ _cairo_glitz_surface_get_image (cairo_gl
static cairo_status_t
_cairo_glitz_surface_set_image (void *abstract_surface,
cairo_image_surface_t *image,
- int x_dst,
- int y_dst)
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ int x_dst,
+ int y_dst)
{
cairo_glitz_surface_t *surface = abstract_surface;
glitz_buffer_t *buffer;
@@ -265,8 +269,8 @@ _cairo_glitz_surface_set_image (void
pf.masks.red_mask = rm;
pf.masks.green_mask = gm;
pf.masks.blue_mask = bm;
- pf.xoffset = 0;
- pf.skip_lines = 0;
+ pf.xoffset = src_x;
+ pf.skip_lines = src_y;
/* check for negative stride */
if (image->stride < 0)
@@ -288,7 +292,7 @@ _cairo_glitz_surface_set_image (void
glitz_set_pixels (surface->surface,
x_dst, y_dst,
- image->width, image->height,
+ width, height,
&pf,
buffer);
@@ -348,7 +352,8 @@ _cairo_glitz_surface_release_dest_image
{
cairo_glitz_surface_t *surface = abstract_surface;
- _cairo_glitz_surface_set_image (surface, image,
+ _cairo_glitz_surface_set_image (surface, image, 0, 0,
+ image->width, image->height,
image_rect->x, image_rect->y);
cairo_surface_destroy (&image->base);
@@ -357,6 +362,10 @@ _cairo_glitz_surface_release_dest_image
static cairo_status_t
_cairo_glitz_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out)
{
cairo_glitz_surface_t *surface = abstract_surface;
@@ -385,7 +394,8 @@ _cairo_glitz_surface_clone_similar (void
if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
- _cairo_glitz_surface_set_image (clone, image_src, 0, 0);
+ _cairo_glitz_surface_set_image (clone, image_src, src_x, src_y,
+ width, height, src_x, src_y);
*clone_out = &clone->base;
@@ -1184,7 +1194,7 @@ _cairo_glitz_surface_composite_trapezoid
return CAIRO_STATUS_NO_MEMORY;
}
- _cairo_glitz_surface_set_image (mask, image, 0, 0);
+ _cairo_glitz_surface_set_image (mask, image, src_x, src_y, width, height, 0, 0);
}
_cairo_glitz_surface_set_attributes (src, &attributes);
@@ -2025,6 +2035,10 @@ _cairo_glitz_surface_old_show_glyphs (ca
status =
_cairo_glitz_surface_clone_similar (abstract_surface,
image,
+ src_x,
+ src_y,
+ width,
+ height,
(cairo_surface_t **)
&clone);
if (status)
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 8dc9087..0021ae9 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -665,6 +665,10 @@ _cairo_image_surface_release_dest_image
static cairo_status_t
_cairo_image_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out)
{
cairo_image_surface_t *surface = abstract_surface;
diff --git a/src/cairo-nquartz-surface.c b/src/cairo-nquartz-surface.c
index 1c300b1..5e82616 100644
--- a/src/cairo-nquartz-surface.c
+++ b/src/cairo-nquartz-surface.c
@@ -498,7 +498,8 @@ SurfacePatternDrawFunc (void *info, CGCo
cairo_surface_t *new_surf = NULL;
- _cairo_surface_clone_similar (dummy, pat_surf, &new_surf);
+ _cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
+ rect.width, rect.height, &new_surf);
cairo_surface_destroy(dummy);
@@ -1025,6 +1026,10 @@ _cairo_nquartz_surface_create_similar (v
static cairo_status_t
_cairo_nquartz_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out)
{
cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
@@ -1104,7 +1109,7 @@ _cairo_nquartz_surface_clone_similar (vo
nquartz_image_to_png (quartz_image, NULL);
CGContextDrawImage (new_surface->cgContext,
- CGRectMake (0, 0, CGImageGetWidth (quartz_image), CGImageGetHeight (quartz_image)),
+ CGRectMake (src_x, src_y, width, height),
quartz_image);
CGImageRelease (quartz_image);
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 5f1dd8a..0d0940f 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1005,7 +1005,8 @@ _cairo_pattern_acquire_surface_for_gradi
pixman_image_destroy (pixman_image);
- status = _cairo_surface_clone_similar (dst, &image->base, out);
+ status = _cairo_surface_clone_similar (dst, &image->base,
+ 0, 0, width, height, out);
cairo_surface_destroy (&image->base);
@@ -1125,6 +1126,22 @@ _cairo_pattern_acquire_surface_for_surfa
attr->acquired = FALSE;
+ attr->extend = pattern->base.extend;
+ attr->filter = pattern->base.filter;
+ if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
+ &tx, &ty))
+ {
+ cairo_matrix_init_identity (&attr->matrix);
+ attr->x_offset = tx;
+ attr->y_offset = ty;
+ attr->filter = CAIRO_FILTER_NEAREST;
+ }
+ else
+ {
+ attr->matrix = pattern->base.matrix;
+ attr->x_offset = attr->y_offset = 0;
+ }
+
if (_cairo_surface_is_image (dst))
{
cairo_image_surface_t *image;
@@ -1140,23 +1157,8 @@ _cairo_pattern_acquire_surface_for_surfa
}
else
{
- status = _cairo_surface_clone_similar (dst, pattern->surface, out);
- }
-
- attr->extend = pattern->base.extend;
- attr->filter = pattern->base.filter;
- if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
- &tx, &ty))
- {
- cairo_matrix_init_identity (&attr->matrix);
- attr->x_offset = tx;
- attr->y_offset = ty;
- attr->filter = CAIRO_FILTER_NEAREST;
- }
- else
- {
- attr->matrix = pattern->base.matrix;
- attr->x_offset = attr->y_offset = 0;
+ status = _cairo_surface_clone_similar (dst, pattern->surface,
+ x+tx, y+ty, width, height, out);
}
return status;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index cbbe89a..dfcf39d 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -987,6 +987,10 @@ _cairo_surface_release_dest_image (cairo
* _cairo_surface_clone_similar:
* @surface: a #cairo_surface_t
* @src: the source image
+ * @src_x: extent for the rectangle in src we actually care about
+ * @src_y: extent for the rectangle in src we actually care about
+ * @width: extent for the rectangle in src we actually care about
+ * @height: extent for the rectangle in src we actually care about
* @clone_out: location to store a surface compatible with @surface
* and with contents identical to @src. The caller must call
* cairo_surface_destroy() on the result.
@@ -1002,6 +1006,10 @@ _cairo_surface_release_dest_image (cairo
cairo_status_t
_cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out)
{
cairo_status_t status;
@@ -1014,7 +1022,8 @@ _cairo_surface_clone_similar (cairo_surf
if (surface->backend->clone_similar == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
- status = surface->backend->clone_similar (surface, src, clone_out);
+ status = surface->backend->clone_similar (surface, src, src_x, src_y,
+ width, height, clone_out);
if (status == CAIRO_STATUS_SUCCESS)
(*clone_out)->device_transform = src->device_transform;
@@ -1025,7 +1034,8 @@ _cairo_surface_clone_similar (cairo_surf
if (status != CAIRO_STATUS_SUCCESS)
return status;
- status = surface->backend->clone_similar (surface, &image->base, clone_out);
+ status = surface->backend->clone_similar (surface, &image->base, src_x,
+ src_y, width, height, clone_out);
if (status == CAIRO_STATUS_SUCCESS)
(*clone_out)->device_transform = src->device_transform;
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 4039605..d104adf 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -642,6 +642,10 @@ _cairo_xcb_surface_same_screen (cairo_xc
static cairo_status_t
_cairo_xcb_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out)
{
cairo_xcb_surface_t *surface = abstract_surface;
@@ -668,6 +672,11 @@ _cairo_xcb_surface_clone_similar (void
if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
+ /* can't apply extents; no manpages for XCBPutImage and xcb
+ source from freedesktop currently won't build. XCBPutImage is not
+ referenced in the XCB source from xcb.freedesktop.org/dist
+ anywhere. */
+
_draw_image_surface (clone, image_src, 0, 0);
*clone_out = &clone->base;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index d0f9158..aaf43e4 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -744,6 +744,10 @@ _cairo_xlib_surface_ensure_gc (cairo_xli
static cairo_status_t
_draw_image_surface (cairo_xlib_surface_t *surface,
cairo_image_surface_t *image,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
int dst_x,
int dst_y)
{
@@ -774,8 +778,8 @@ _draw_image_surface (cairo_xlib_surface_
_cairo_xlib_surface_ensure_gc (surface);
XPutImage(surface->dpy, surface->drawable, surface->gc,
- &ximage, 0, 0, dst_x, dst_y,
- image->width, image->height);
+ &ximage, src_x, src_y, dst_x, dst_y,
+ width, height);
return CAIRO_STATUS_SUCCESS;
@@ -839,7 +843,8 @@ _cairo_xlib_surface_release_dest_image (
cairo_xlib_surface_t *surface = abstract_surface;
/* ignore errors */
- _draw_image_surface (surface, image, image_rect->x, image_rect->y);
+ _draw_image_surface (surface, image, 0, 0, image->width, image->height,
+ image_rect->x, image_rect->y);
cairo_surface_destroy (&image->base);
}
@@ -859,6 +864,10 @@ _cairo_xlib_surface_same_screen (cairo_x
static cairo_status_t
_cairo_xlib_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out)
{
cairo_xlib_surface_t *surface = abstract_surface;
@@ -884,7 +893,8 @@ _cairo_xlib_surface_clone_similar (void
if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
- _draw_image_surface (clone, image_src, 0, 0);
+ _draw_image_surface (clone, image_src, src_x, src_y,
+ width, height, src_x, src_y);
*clone_out = &clone->base;
diff --git a/src/cairoint.h b/src/cairoint.h
index 17482f5..2c5856d 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -723,6 +723,10 @@ struct _cairo_surface_backend {
cairo_status_t
(*clone_similar) (void *surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out);
/* XXX: dst should be the first argument for consistency */
@@ -1885,6 +1889,10 @@ _cairo_surface_release_dest_image (cairo
cairo_private cairo_status_t
_cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
cairo_surface_t **clone_out);
cairo_private cairo_surface_t *
More information about the cairo-commit
mailing list