[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