[cairo] slow path annotations

Jeff Muizelaar jeff at infidigm.net
Thu Mar 8 08:37:48 PST 2007


The following patch annotates some of the slow paths in cairo with
cairo_slow_path() or pixman_slow_path() as appropriate. If either of
these functions is called, cairo will raise a SIGTRAP. 

If you run the applications with gdb, the SIGTRAP will stop the
application and you will be able to get a backtrace to see what caused
the slow path to be called. After determining the cause, you can either
fix cairo or fix your application.

For example, glitz-test currently draws it's rgba(0,0,0,1) text with
OPERATOR_SOURCE. OPERATOR_SOURCE through a mask is a slow path. Changing
this to OPERATOR_OVER (probably the wanted operator anyways) gives me
about a 3-4fps speed up (old=22fps, new=25fps) using software rendering.

Note, X has the pretty much the same slow paths as pixman, however this
patch will not catch them. You can fix this by rending to a temporary
image surface and then set_source'ing and painting to your X cairo
context.

-Jeff

diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c
index 233b90c..8f5cb87 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -4206,6 +4206,10 @@ pixman_compositeGeneral (pixman_operator_t	op,
     CARD32 *scanline_buffer = _scanline_buffer;
     FbComposeData compose_data;
 
+    /* Don't treat gradients as a slow path because there is no fast path */
+    if (pSrc->pDrawable)
+	    pixman_slow_path();
+
     if (pSrc->pDrawable)
         srcRepeat = pSrc->repeat == RepeatNormal && !pSrc->transform
                     && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c
index 0bd989f..af3ff26 100644
--- a/pixman/src/fbpict.c
+++ b/pixman/src/fbpict.c
@@ -1951,6 +1951,14 @@ pixman_composite (pixman_operator_t	op,
 
     n = pixman_region_num_rects (region);
     pbox = pixman_region_rects (region);
+
+    /* check for compositing a solid surface without a solid varient */
+    if (srcRepeat && pSrc->pDrawable &&
+		    pSrc->pDrawable->height == 1 &&
+		    pSrc->pDrawable->width == 1 &&
+		    (pbox->y2 - pbox->y1 > 1 || pbox->x2 - pbox->x1 > 1))
+	    pixman_slow_path();
+
     while (n--)
     {
 	h = pbox->y2 - pbox->y1;
diff --git a/pixman/src/icint.h b/pixman/src/icint.h
index 47a2220..46cf955 100644
--- a/pixman/src/icint.h
+++ b/pixman/src/icint.h
@@ -117,6 +117,12 @@ typedef pixman_triangle_t	xTriangle;
 #define MAXSHORT SHRT_MAX
 #define MINSHORT SHRT_MIN
 
+#include <signal.h>
+static inline void pixman_slow_path(void)
+{
+	raise(5);
+}
+
 /* XXX: What do we need from here?
 #include "picture.h"
 */
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 1a7d666..3a0cf0f 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -284,14 +284,15 @@ _clip_and_composite_source (cairo_clip_t                  *clip,
     cairo_surface_pattern_t mask_pattern;
     cairo_status_t status;
 
+    /* Single composite operation becomes two.
+     * Two, that are likely not fast */
+    /* If you hit this maybe you should be using OVER instead of SOURCE */
+    cairo_slow_path();
+
     /* Create a surface that is mask IN clip
      */
-    status = _create_composite_mask_pattern (&mask_pattern,
-					     clip,
-					     draw_func, draw_closure,
-					     dst, extents);
-    if (status)
-	return status;
+    status = _create_composite_mask_pattern (&mask_pattern, clip, draw_func,
+		    draw_closure, dst, extents); if (status) return status;
 
     /* Compute dest' = dest OUT (mask IN clip)
      */
diff --git a/src/cairoint.h b/src/cairoint.h
index 19897ff..4ccea82 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -272,6 +272,12 @@ typedef cairo_fixed_16_16_t cairo_fixed_t;
 #define CAIRO_BITSWAP8_IF_LITTLE_ENDIAN(c) CAIRO_BITSWAP8(c)
 #endif
 
+#include <signal.h>
+static inline void cairo_slow_path(void)
+{
+	raise(5);
+}
+
 #include "cairo-hash-private.h"
 #include "cairo-cache-private.h"
 


More information about the cairo mailing list