diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-22 00:36:03 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-26 14:55:58 +0100 |
commit | a69335a84eb9225b477cc8c753470eb3805b852c (patch) | |
tree | 7a28492ebf390e513391af587f00c017e4ca6301 /util | |
parent | c6812c6a3679c3b8b9584e119e0d7fd93e09ae49 (diff) |
API: map-to-image and create-similar-image
A common requirement is the fast upload of pixel data. In order to
allocate the most appropriate image buffer, we need knowledge of the
destination. The most obvious example is that we could use a
shared-memory region for the image to avoid the transfer cost of
uploading the pixels to the X server. Similarly, gl, win32, quartz...
The other side of the equation is that for manual modification of a
remote surface, it would be more efficient if we can create a similar
image to reduce the transfer costs. This strategy is already followed
for the destination fallbacks and this merely exposes the same
capability for the application fallbacks.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'util')
-rw-r--r-- | util/cairo-script/cairo-script-operators.c | 96 | ||||
-rw-r--r-- | util/cairo-trace/trace.c | 92 |
2 files changed, 188 insertions, 0 deletions
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c index ef96e447..a45201f7 100644 --- a/util/cairo-script/cairo-script-operators.c +++ b/util/cairo-script/cairo-script-operators.c @@ -3620,6 +3620,67 @@ _matrix (csi_t *ctx) } static csi_status_t +_map_to_image (csi_t *ctx) +{ + csi_object_t obj; + csi_array_t *array; + csi_status_t status; + cairo_rectangle_t extents; + cairo_rectangle_t *r; + cairo_surface_t *surface; + + check (2); + + status = _csi_ostack_get_array (ctx, 0, &array); + if (_csi_unlikely (status)) + return status; + + status = _csi_ostack_get_surface (ctx, 1, &surface); + if (_csi_unlikely (status)) + return status; + + switch (array->stack.len) { + case 0: + r = NULL; + case 4: + extents.x = _csi_object_as_real (&array->stack.objects[0]); + extents.y = _csi_object_as_real (&array->stack.objects[1]); + extents.width = _csi_object_as_real (&array->stack.objects[2]); + extents.height = _csi_object_as_real (&array->stack.objects[3]); + r = &extents; + break; + default: + return _csi_error (CSI_STATUS_INVALID_SCRIPT); + } + + obj.type = CSI_OBJECT_TYPE_SURFACE; + obj.datum.surface = cairo_surface_map_to_image (surface, r); + pop (2); + return push (&obj); +} + +static csi_status_t +_unmap_image (csi_t *ctx) +{ + cairo_surface_t *surface, *image; + csi_status_t status; + + check (2); + + status = _csi_ostack_get_surface (ctx, 0, &image); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_surface (ctx, 1, &surface); + if (_csi_unlikely (status)) + return status; + + cairo_surface_unmap_image (surface, image); + + pop (2); + return CSI_STATUS_SUCCESS; +} + +static csi_status_t _mesh (csi_t *ctx) { csi_object_t obj; @@ -5521,6 +5582,38 @@ _similar (csi_t *ctx) } static csi_status_t +_similar_image (csi_t *ctx) +{ + csi_object_t obj; + long format; + double width, height; + cairo_surface_t *other; + csi_status_t status; + + check (4); + + status = _csi_ostack_get_number (ctx, 0, &height); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 1, &width); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_integer (ctx, 2, &format); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_surface (ctx, 3, &other); + if (_csi_unlikely (status)) + return status; + + obj.type = CSI_OBJECT_TYPE_SURFACE; + obj.datum.surface = cairo_surface_create_similar_image (other, + format, + width, height); + pop (4); + return push (&obj); +} + +static csi_status_t _subsurface (csi_t *ctx) { csi_object_t obj; @@ -6301,6 +6394,7 @@ _defs[] = { { "lt", _lt }, { "m", _move_to }, { "M", _rel_move_to }, + { "map-to-image", _map_to_image }, { "mark", _mark }, { "mask", _mask }, { "matrix", _matrix }, @@ -6381,6 +6475,7 @@ _defs[] = { { "show-text-glyphs", _show_text_glyphs }, { "show-page", _show_page }, { "similar", _similar }, + { "similar-image", _similar_image }, { "sin", NULL }, { "sqrt", NULL }, { "sub", _sub }, @@ -6399,6 +6494,7 @@ _defs[] = { { "true", _true }, { "type", NULL }, { "undef", _undef }, + { "unmap-image", _unmap_image }, { "unset", _unset }, { "user-to-device", NULL }, { "user-to-device-distance", NULL }, diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c index 9c59b1d6..9337a3bd 100644 --- a/util/cairo-trace/trace.c +++ b/util/cairo-trace/trace.c @@ -3511,6 +3511,98 @@ cairo_surface_create_similar (cairo_surface_t *other, } cairo_surface_t * +cairo_surface_create_similar_image (cairo_surface_t *other, + cairo_format_t format, + int width, int height) +{ + cairo_surface_t *ret; + + _enter_trace (); + + ret = DLCALL (cairo_surface_create_similar_image, + other, format, width, height); + + _emit_line_info (); + if (other != NULL && _write_lock ()) { + Object *other_obj = _get_object(SURFACE, other); + Object *new_obj = _create_surface (ret); + + if (other_obj->defined) + _trace_printf ("s%ld ", other_obj->token); + else if (current_stack_depth == other_obj->operand + 1) + _trace_printf ("dup "); + else + _trace_printf ("%d index ", + current_stack_depth - other_obj->operand - 1); + _trace_printf ("s%ld //%s %d %d similar-image %% s%ld\n", + _get_surface_id (other), + _format_to_string (format), + width, height, + new_obj->token); + + _push_object (new_obj); + _write_unlock (); + } + + _exit_trace (); + return ret; +} + +cairo_surface_t * +cairo_surface_map_to_image (cairo_surface_t *surface, + const cairo_rectangle_t *extents) +{ + cairo_surface_t *ret; + + _enter_trace (); + + ret = DLCALL (cairo_surface_map_to_image, surface, extents); + + _emit_line_info (); + if (_write_lock ()) { + Object *obj = _create_surface (ret); + + if (extents) { + _trace_printf ("[ %f %f %f %f ] map-to-image dup /s%ld exch def\n", + extents->x, extents->y, + extents->width, + extents->height, + obj->token); + obj->width = extents->width; + obj->height = extents->height; + } else { + _trace_printf ("[ ] map-to-image dup /s%ld exch def\n", + obj->token); + } + obj->defined = TRUE; + _push_object (obj); + _write_unlock (); + } + + _exit_trace (); + return ret; +} + +void +cairo_surface_unmap_image (cairo_surface_t *surface, + cairo_surface_t *image) +{ + _enter_trace (); + + _emit_line_info (); + if (_write_lock ()) { + _trace_printf ("/s%ld /s%ld unmap-image\n", + _get_surface_id (surface), + _get_surface_id (image)); + _write_unlock (); + } + + DLCALL (cairo_surface_unmap_image, surface, image); + + _exit_trace (); +} + +cairo_surface_t * cairo_surface_create_for_rectangle (cairo_surface_t *target, double x, double y, double width, double height) |