[cairo-commit] 4 commits - src/cairo-composite-rectangles.c src/cairo-recording-surface.c src/cairo-recording-surface-private.h src/cairo-surface-observer.c src/cairo-xlib-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Sat Aug 20 04:58:18 PDT 2011


 src/cairo-composite-rectangles.c      |    2 
 src/cairo-recording-surface-private.h |    1 
 src/cairo-recording-surface.c         |   12 +-
 src/cairo-surface-observer.c          |  159 ++++++++++++++++++++++------------
 src/cairo-xlib-surface.c              |    2 
 5 files changed, 112 insertions(+), 64 deletions(-)

New commits:
commit 4d6c62514ccd9604af29df0d24e74e5d24f4607d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 20 13:02:00 2011 +0100

    observer: bypass surface mid-layer and call into recording surface directly
    
    As we want to record the exact command pass to us, we want to bypass any
    further optimisations that the surface mid-layer might perform before
    passing the operation to the recording surface.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 9cc597f..432e0d2 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -477,7 +477,7 @@ record_target (cairo_observation_record_t *r,
     }
 }
 
-static void
+static cairo_observation_record_t *
 record_paint (cairo_observation_record_t *r,
 	      cairo_surface_t *target,
 	      cairo_operator_t op,
@@ -497,9 +497,11 @@ record_paint (cairo_observation_record_t *r,
     r->antialias = -1;
     r->clip = classify_clip (clip);
     r->elapsed = elapsed;
+
+    return r;
 }
 
-static void
+static cairo_observation_record_t *
 record_mask (cairo_observation_record_t *r,
 	     cairo_surface_t *target,
 	     cairo_operator_t op,
@@ -520,9 +522,11 @@ record_mask (cairo_observation_record_t *r,
     r->antialias = -1;
     r->clip = classify_clip (clip);
     r->elapsed = elapsed;
+
+    return r;
 }
 
-static void
+static cairo_observation_record_t *
 record_fill (cairo_observation_record_t *r,
 	     cairo_surface_t		*target,
 	     cairo_operator_t		op,
@@ -546,9 +550,11 @@ record_fill (cairo_observation_record_t *r,
     r->antialias = antialias;
     r->clip = classify_clip (clip);
     r->elapsed = elapsed;
+
+    return r;
 }
 
-static void
+static cairo_observation_record_t *
 record_stroke (cairo_observation_record_t *r,
 	       cairo_surface_t		*target,
 	       cairo_operator_t		op,
@@ -574,9 +580,11 @@ record_stroke (cairo_observation_record_t *r,
     r->antialias = antialias;
     r->clip = classify_clip (clip);
     r->elapsed = elapsed;
+
+    return r;
 }
 
-static void
+static cairo_observation_record_t *
 record_glyphs (cairo_observation_record_t *r,
 	       cairo_surface_t		*target,
 	       cairo_operator_t		op,
@@ -599,6 +607,8 @@ record_glyphs (cairo_observation_record_t *r,
     r->antialias = -1;
     r->clip = classify_clip (clip);
     r->elapsed = elapsed;
+
+    return r;
 }
 
 static void
@@ -608,7 +618,7 @@ add_record (cairo_observation_t *log,
 {
     cairo_int_status_t status;
 
-    r->index = index - 1;
+    r->index = index;
 
     status = _cairo_array_append (&log->timings, r);
     assert (status == CAIRO_INT_STATUS_SUCCESS);
@@ -666,11 +676,18 @@ add_record_paint (cairo_observation_t *log,
     cairo_observation_record_t record;
     cairo_int_status_t status;
 
-    record_paint (&record, target, op, source, clip, elapsed);
+    add_record (log,
+		record_paint (&record, target, op, source, clip, elapsed),
+		log->record->commands.num_elements);
 
-    status = _cairo_surface_paint (&log->record->base, op, source, clip);
+    /* We have to bypass the high-level surface layer in case it tries to be
+     * too smart and discard operations; we need to record exactly what just
+     * happened on the target.
+     */
+    status = log->record->base.backend->paint (&log->record->base,
+					       op, source, clip);
     assert (status == CAIRO_INT_STATUS_SUCCESS);
-    add_record (log, &record, log->record->commands.num_elements);
+    assert (log->record->commands.num_elements == record.index + 1);
 
     if (elapsed > log->paint.slowest.elapsed)
 	log->paint.slowest = record;
@@ -749,12 +766,13 @@ add_record_mask (cairo_observation_t *log,
     cairo_observation_record_t record;
     cairo_int_status_t status;
 
-    record_mask (&record, target, op, source, mask, clip, elapsed);
+    add_record (log,
+		record_mask (&record, target, op, source, mask, clip, elapsed),
+		log->record->commands.num_elements);
 
-    status = _cairo_surface_mask (&log->record->base,
-				  op, source, mask, clip);
+    status = log->record->base.backend->mask (&log->record->base,
+					      op, source, mask, clip);
     assert (status == CAIRO_INT_STATUS_SUCCESS);
-    add_record (log, &record, log->record->commands.num_elements);
 
     if (elapsed > log->mask.slowest.elapsed)
 	log->mask.slowest = record;
@@ -841,17 +859,19 @@ add_record_fill (cairo_observation_t *log,
     cairo_observation_record_t record;
     cairo_int_status_t status;
 
-    record_fill (&record,
-		 target, op, source,
-		 path, fill_rule, tolerance, antialias,
-		 clip, elapsed);
-
-    status = _cairo_surface_fill (&log->record->base,
-				  op, source,
-				  path, fill_rule, tolerance, antialias,
-				  clip);
+    add_record (log,
+		record_fill (&record,
+			     target, op, source,
+			     path, fill_rule, tolerance, antialias,
+			     clip, elapsed),
+		log->record->commands.num_elements);
+
+    status = log->record->base.backend->fill (&log->record->base,
+					      op, source,
+					      path, fill_rule,
+					      tolerance, antialias,
+					      clip);
     assert (status == CAIRO_INT_STATUS_SUCCESS);
-    add_record (log, &record, log->record->commands.num_elements);
 
     if (elapsed > log->fill.slowest.elapsed)
 	log->fill.slowest = record;
@@ -951,19 +971,20 @@ add_record_stroke (cairo_observation_t *log,
     cairo_observation_record_t record;
     cairo_int_status_t status;
 
-    record_stroke (&record,
-		   target, op, source,
-		   path, style, ctm,ctm_inverse,
-		   tolerance, antialias,
-		   clip, elapsed);
-
-    status = _cairo_surface_stroke (&log->record->base,
-				    op, source,
-				    path, style, ctm,ctm_inverse,
-				    tolerance, antialias,
-				    clip);
+    add_record (log,
+		record_stroke (&record,
+			       target, op, source,
+			       path, style, ctm,ctm_inverse,
+			       tolerance, antialias,
+			       clip, elapsed),
+		log->record->commands.num_elements);
+
+    status = log->record->base.backend->stroke (&log->record->base,
+						op, source,
+						path, style, ctm,ctm_inverse,
+						tolerance, antialias,
+						clip);
     assert (status == CAIRO_INT_STATUS_SUCCESS);
-    add_record (log, &record, log->record->commands.num_elements);
 
     if (elapsed > log->stroke.slowest.elapsed)
 	log->stroke.slowest = record;
@@ -1068,19 +1089,21 @@ add_record_glyphs (cairo_observation_t	*log,
     cairo_observation_record_t record;
     cairo_int_status_t status;
 
-    record_glyphs (&record,
-		   target, op, source,
-		   glyphs, num_glyphs, scaled_font,
-		   clip, elapsed);
+    add_record (log,
+		record_glyphs (&record,
+			       target, op, source,
+			       glyphs, num_glyphs, scaled_font,
+			       clip, elapsed),
+		log->record->commands.num_elements);
 
-    status = _cairo_surface_show_text_glyphs (&log->record->base, op, source,
-					      NULL, 0,
-					      glyphs, num_glyphs,
-					      NULL, 0, 0,
-					      scaled_font,
-					      clip);
+    status = log->record->base.backend->show_text_glyphs (&log->record->base,
+							  op, source,
+							  NULL, 0,
+							  glyphs, num_glyphs,
+							  NULL, 0, 0,
+							  scaled_font,
+							  clip);
     assert (status == CAIRO_INT_STATUS_SUCCESS);
-    add_record (log, &record, log->record->commands.num_elements);
 
     if (elapsed > log->glyphs.slowest.elapsed)
 	log->glyphs.slowest = record;
commit f49dae8013cf089e18b333a686a7e30c212e4fae
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 20 13:01:01 2011 +0100

    observer: copy glyphs around call into backend
    
    As the backend is allowed to modify the glyph array, we need to copy it
    for recoding.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 370b05b..9cc597f 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -1102,6 +1102,7 @@ _cairo_surface_observer_glyphs (void			*abstract_surface,
     cairo_composite_rectangles_t composite;
     cairo_rectangle_int_t extents;
     cairo_int_status_t status;
+    cairo_glyph_t *dev_glyphs;
     struct timespec ts;
     double elapsed;
     int x, y;
@@ -1136,14 +1137,22 @@ _cairo_surface_observer_glyphs (void			*abstract_surface,
     add_extents (&device->log.glyphs.extents, &composite);
     _cairo_composite_rectangles_fini (&composite);
 
+    /* XXX We have to copy the glyphs, because the backend is allowed to
+     * modify! */
+    dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+    if (unlikely (dev_glyphs == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    memcpy (dev_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+
     *remaining_glyphs = 0;
     start_timer (&ts);
     status = _cairo_surface_show_text_glyphs (surface->target, op, source,
-					    NULL, 0,
-					    glyphs, num_glyphs,
-					    NULL, 0, 0,
-					    scaled_font,
-					    clip);
+					      NULL, 0,
+					      dev_glyphs, num_glyphs,
+					      NULL, 0, 0,
+					      scaled_font,
+					      clip);
+    free (dev_glyphs);
     if (unlikely (status))
 	return status;
 
commit cb243acee59be4802153d7e18ef25d24815bb2e4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 20 12:48:25 2011 +0100

    recording: optionally disable optimise away clears
    
    The observer wants to get an accurate recording of all operations,
    including clears.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c
index 6083973..a25e6d3 100644
--- a/src/cairo-composite-rectangles.c
+++ b/src/cairo-composite-rectangles.c
@@ -224,9 +224,7 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
 
     if (! _cairo_composite_rectangles_init (extents, unbounded,
 					    op, source, clip))
-    {
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
-    }
 
     /* Computing the exact bbox and the overlap is expensive.
      * First perform a cheap test to see if the glyphs are all clipped out.
diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h
index b7843e6..ea38c19 100644
--- a/src/cairo-recording-surface-private.h
+++ b/src/cairo-recording-surface-private.h
@@ -134,6 +134,7 @@ typedef struct _cairo_recording_surface {
     cairo_array_t commands;
     int *indices;
     int num_indices;
+    cairo_bool_t optimize_clears;
 
     struct bbtree {
 	cairo_box_t extents;
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index beafb78..6d4cb37 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -413,6 +413,7 @@ cairo_recording_surface_create (cairo_content_t		 content,
 
     surface->indices = NULL;
     surface->num_indices = 0;
+    surface->optimize_clears = TRUE;
 
     return &surface->base;
 }
@@ -714,13 +715,12 @@ _cairo_recording_surface_paint (void			  *abstract_surface,
     cairo_composite_rectangles_t composite;
     const cairo_rectangle_int_t *extents;
 
-    /* An optimisation that takes care to not replay what was done
-     * before surface is cleared. We don't erase recorded commands
-     * since we may have earlier snapshots of this surface. */
     if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
-	_cairo_recording_surface_destroy_bbtree (surface);
-	surface->commands.num_elements = 0;
-	return CAIRO_STATUS_SUCCESS;
+	if (surface->optimize_clears) {
+	    _cairo_recording_surface_destroy_bbtree (surface);
+	    surface->commands.num_elements = 0;
+	    return CAIRO_STATUS_SUCCESS;
+	}
     }
 
     extents = _cairo_recording_surface_extents (surface);
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index abb00e7..370b05b 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -113,7 +113,7 @@ static void init_glyphs (struct glyphs *g)
     init_clip (&g->clip);
 }
 
-static void
+static cairo_status_t
 log_init (cairo_observation_t *log)
 {
     memset (log, 0, sizeof(*log));
@@ -125,8 +125,15 @@ log_init (cairo_observation_t *log)
     init_glyphs (&log->glyphs);
 
     _cairo_array_init (&log->timings, sizeof (cairo_observation_record_t));
+
     log->record = (cairo_recording_surface_t *)
 	    cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
+    if (unlikely (log->record->base.status))
+	return log->record->base.status;
+
+    log->record->optimize_clears = FALSE;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -323,15 +330,20 @@ static cairo_device_t *
 _cairo_device_create_observer_internal (cairo_device_t *target)
 {
     cairo_device_observer_t *device;
+    cairo_status_t status;
 
     device = malloc (sizeof (cairo_device_observer_t));
     if (unlikely (device == NULL))
 	return _cairo_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
     _cairo_device_init (&device->base, &_cairo_device_observer_backend);
-    device->target = cairo_device_reference (target);
+    status = log_init (&device->log);
+    if (unlikely (status)) {
+	free (device);
+	return _cairo_device_create_in_error (status);
+    }
 
-    log_init (&device->log);
+    device->target = cairo_device_reference (target);
 
     return &device->base;
 }
@@ -349,6 +361,7 @@ _cairo_surface_create_observer_internal (cairo_device_t *device,
 					 cairo_surface_t *target)
 {
     cairo_surface_observer_t *surface;
+    cairo_status_t status;
 
     surface = malloc (sizeof (cairo_surface_observer_t));
     if (unlikely (surface == NULL))
@@ -358,7 +371,11 @@ _cairo_surface_create_observer_internal (cairo_device_t *device,
 			 &_cairo_surface_observer_backend, device,
 			 target->content);
 
-    log_init (&surface->log);
+    status = log_init (&surface->log);
+    if (unlikely (status)) {
+	free (surface);
+	return _cairo_surface_create_in_error (status);
+    }
 
     surface->target = cairo_surface_reference (target);
     surface->base.type = surface->target->type;
commit 236cb8aa22f780b24e1d1485dc1f5384946fe181
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 20 12:01:09 2011 +0100

    xlib: Fix typo in snapshotting.
    
    We want to only copy up to the maximum height, not width...
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 6cc215b..96d5993 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1395,7 +1395,7 @@ _cairo_xlib_surface_snapshot (void *abstract_surface)
 
     extents.x = extents.y = 0;
     extents.width = surface->width;
-    extents.height = surface->width;
+    extents.height = surface->height;
 
     /* XXX notice the duplication */
     return _get_image_surface (surface, &extents);


More information about the cairo-commit mailing list