Re: Horribly slow rendering using Quartz surfaces

Andrea Canciani <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <CAN_5=BDT8exAa61XTfDDsNUnAyftL1RZJ56sBg7FNmHYnO9vAg@mail.gmail.com>
On Tue, Aug 6, 2013 at 4:34 PM, Bobby Salazar <[email protected]> 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
> [email protected]
> http://lists.cairographics.org/mailman/listinfo/cairo
>

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.