[cairo] Horribly slow rendering using Quartz surfaces
Andrea Canciani
ranma42 at gmail.com
Thu Sep 12 06:42:38 PDT 2013
On my system, running your code on image 10000 times takes ~ 0.3 seconds,
while on a quartz surface it takes about 3 seconds.
If I completely disable the gradient evaluation (ComputeGradientValue
always returns [0,0,0,0] without performing any computation at all), quartz
improves a little, as it only takes about 2 seconds, but it is still much
slower than pixman, apparently because it spends a lot of time in
colorspace conversion.
I started to port the pixman gradient evaluation code (the REFLECT case,
which is the one hit by your code), but the improvement I got is less than
10%, which might not be worth the additional complexity.
Andrea
On Wed, Aug 21, 2013 at 4:40 PM, Andrea Canciani <ranma42 at gmail.com> wrote:
> On Tue, Aug 6, 2013 at 4:34 PM, Bobby Salazar <bobby8934 at gmail.com> wrote:
>
>> 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.
>
>
> My profiling seems to show that the code path for the Quartz rendering
> does not involve Pixman.
>
>
>> 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?
>>
>
> Instead of using Pixman, cairo-quartz is using the native Quartz radial
> gradient implementation.
> The radial gradient implementation in Pixman has been tuned quite a lot to
> achieve high performance.
>
>
>>
>> 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?
>>
>
> Apparently the main slow-down comes from the evaluation of
> ComputeGradientValue.
> It should be possible to improve its performance by precomputing some more
> information (example: the 1/bx coefficient), by caching the current
> position with respect to the gradient stops (to reduce the lookup time for
> the correct position) and by avoiding calls to fmod/floor/... function when
> it is not actually needed (this is hit by your gradient, in particular).
>
> As you might have noticed, recently I did not have much time to work on
> cairo.
> I will try to prepare a patch in the next days, but if my guess is
> incorrect (that is, if the slowdown does not just depends on the things I
> pointed out above), I might be unable to get it done before September.
>
> Andrea
>
>
>
>> --
>> cairo mailing list
>> cairo at cairographics.org
>> http://lists.cairographics.org/mailman/listinfo/cairo
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cairographics.org/archives/cairo/attachments/20130912/a1cf1829/attachment-0001.html>
More information about the cairo
mailing list