summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-07-22 00:36:03 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-07-26 14:55:58 +0100
commita69335a84eb9225b477cc8c753470eb3805b852c (patch)
tree7a28492ebf390e513391af587f00c017e4ca6301 /util
parentc6812c6a3679c3b8b9584e119e0d7fd93e09ae49 (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.c96
-rw-r--r--util/cairo-trace/trace.c92
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)