[cairo] Horribly slow rendering using Quartz surfaces

Bobby Salazar bobby8934 at gmail.com
Tue Aug 6 16:34:18 PDT 2013


I am testing some code on iOS and have run into a rendering problem
using Quartz surfaces that does not happen by merely switching the
surface out to an image surface. Here is the code:

void TestRadialRender()
{
	cairo_surface_t* pSurface;
	cairo_t* pContext;
	cairo_matrix_t Matrix;
	
	// Setup surface
	//pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 1136);
	pSurface = cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32, 640, 1136);
	pContext = cairo_create(pSurface);
	
	// Setup matrix
	cairo_matrix_init(&Matrix, 3.6, 0.0, 0.0, 1.35, 568, 66);
	cairo_set_matrix(pContext, &Matrix);
	
	// Setup path
	cairo_new_path(pContext);
	double cx = -45.84799;
	double cy = 7.394;
	double rx = 3;
	double ry = 3;
	
	cairo_move_to (pContext, cx + rx, cy);
	cairo_curve_to (pContext, cx + rx, cy + ry * 0.5522847498, cx + rx *
0.5522847498, cy + ry, cx, cy + ry);
	cairo_curve_to (pContext, cx - rx * 0.5522847498, cy + ry, cx - rx,
cy + ry * 0.5522847498, cx - rx, cy);
	cairo_curve_to (pContext, cx - rx, cy - ry * 0.5522847498, cx - rx *
0.5522847498, cy - ry, cx, cy - ry);
	cairo_curve_to (pContext, cx + rx * 0.5522847498, cy - ry, cx + rx,
cy - ry * 0.5522847498, cx + rx, cy);
	cairo_close_path (pContext);

	
	// Setup pattern
	cairo_pattern_t*	pat;
	pat = cairo_pattern_create_radial(-45.84799, 7.394, 0, -45.84799, 7.394, 3);
	cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT);
	
	// Setup brush color
	cairo_pattern_add_color_stop_rgba(pat, 0, 0.00, 0.00, 1.00, 0.125);
	
	// Setup color stops
	cairo_pattern_add_color_stop_rgba(pat, 0.0000, 0.54, 0.55, 0.56, 1.00);
	cairo_pattern_add_color_stop_rgba(pat, 0.1272, 0.67, 0.68, 0.69, 1.00);
	cairo_pattern_add_color_stop_rgba(pat, 0.2750, 0.78, 0.79, 0.80, 1.00);
	cairo_pattern_add_color_stop_rgba(pat, 0.4307, 0.88, 0.88, 0.89, 0.50);
	cairo_pattern_add_color_stop_rgba(pat, 0.5955, 0.95, 0.95, 0.95, 0.25);
	cairo_pattern_add_color_stop_rgba(pat, 0.7757, 0.98, 0.98, 0.98, 0.125);
	cairo_pattern_add_color_stop_rgba(pat, 1.0000, 1.00, 1.00, 1.00, 0.00);
	
	// Render it
	cairo_set_source(pContext, pat);
	
	//// START TIMER ////
	cairo_fill_preserve(pContext);
	//// END TIMER ////
	
	cairo_pattern_destroy(pat);
	
	// Cleanup
	cairo_surface_destroy(pSurface);
	cairo_destroy(pContext);
}


In that test function above, if the code is using
cairo_quartz_surface_create() then the call to cairo_fill_preserve()
takes around 600ms to complete. If you comment out
cairo_quartz_surface_create() and use cairo_image_surface_create()
instead, then the call to cairo_fill_preserve() takes around 2ms to
complete.

In the case where it renders really slow, it is usually stuck down in
the Pixman code calculating radial gradient information. However, I
would expect that it uses the same Pixman code for the image surface
as it does for the Quartz surface type. Does anyone have any ideas
what could be going wrong here?

This testing was done on an iPod touch 5th generation device (ARM
based processor) using Cairo v1.8.0 and Pixman v0.24.0. I realize this
version of Cairo may be a little old now, is anyone able to test this
function using a newer build to see if it may have already been fixed?

As I type this I realize it may be helpful to get numbers on an x86
processor. I ran the same function under the iPhone simulator on a
Core i7 MacBook Pro and it produced 74ms for the Quartz surface and
less than 1 millisecond for the image surface. As you can see, the
Quartz surface is still an order of magnitude slower.

Any ideas?


More information about the cairo mailing list