[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cairo
Subject:    Re: [cairo] Horribly slow rendering using Quartz surfaces
From:       Andrea Canciani <ranma42 () gmail ! com>
Date:       2013-08-21 14:40:31
Message-ID: CAN_5=BDT8exAa61XTfDDsNUnAyftL1RZJ56sBg7FNmHYnO9vAg () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


On Tue, Aug 6, 2013 at 4:34 PM, Bobby Salazar <bobby8934@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@cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo
>

[Attachment #5 (text/html)]

<div dir="ltr">On Tue, Aug 6, 2013 at 4:34 PM, Bobby Salazar <span dir="ltr">&lt;<a \
href="mailto:bobby8934@gmail.com" target="_blank">bobby8934@gmail.com</a>&gt;</span> \
wrote:<br><div class="gmail_extra"><div class="gmail_quote"> <blockquote \
class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex">I am testing some code on iOS and have run into a \
rendering problem<br> using Quartz surfaces that does not happen by merely switching \
the<br> surface out to an image surface. Here is the code:<br>
<br>
void TestRadialRender()<br>
{<br>
        cairo_surface_t* pSurface;<br>
        cairo_t* pContext;<br>
        cairo_matrix_t Matrix;<br>
<br>
        // Setup surface<br>
        //pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 1136);<br>
        pSurface = cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32, 640, 1136);<br>
        pContext = cairo_create(pSurface);<br>
<br>
        // Setup matrix<br>
        cairo_matrix_init(&amp;Matrix, 3.6, 0.0, 0.0, 1.35, 568, 66);<br>
        cairo_set_matrix(pContext, &amp;Matrix);<br>
<br>
        // Setup path<br>
        cairo_new_path(pContext);<br>
        double cx = -45.84799;<br>
        double cy = 7.394;<br>
        double rx = 3;<br>
        double ry = 3;<br>
<br>
        cairo_move_to (pContext, cx + rx, cy);<br>
        cairo_curve_to (pContext, cx + rx, cy + ry * 0.5522847498, cx + rx *<br>
0.5522847498, cy + ry, cx, cy + ry);<br>
        cairo_curve_to (pContext, cx - rx * 0.5522847498, cy + ry, cx - rx,<br>
cy + ry * 0.5522847498, cx - rx, cy);<br>
        cairo_curve_to (pContext, cx - rx, cy - ry * 0.5522847498, cx - rx *<br>
0.5522847498, cy - ry, cx, cy - ry);<br>
        cairo_curve_to (pContext, cx + rx * 0.5522847498, cy - ry, cx + rx,<br>
cy - ry * 0.5522847498, cx + rx, cy);<br>
        cairo_close_path (pContext);<br>
<br>
<br>
        // Setup pattern<br>
        cairo_pattern_t*        pat;<br>
        pat = cairo_pattern_create_radial(-45.84799, 7.394, 0, -45.84799, 7.394, \
3);<br>  cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT);<br>
<br>
        // Setup brush color<br>
        cairo_pattern_add_color_stop_rgba(pat, 0, 0.00, 0.00, 1.00, 0.125);<br>
<br>
        // Setup color stops<br>
        cairo_pattern_add_color_stop_rgba(pat, 0.0000, 0.54, 0.55, 0.56, 1.00);<br>
        cairo_pattern_add_color_stop_rgba(pat, 0.1272, 0.67, 0.68, 0.69, 1.00);<br>
        cairo_pattern_add_color_stop_rgba(pat, 0.2750, 0.78, 0.79, 0.80, 1.00);<br>
        cairo_pattern_add_color_stop_rgba(pat, 0.4307, 0.88, 0.88, 0.89, 0.50);<br>
        cairo_pattern_add_color_stop_rgba(pat, 0.5955, 0.95, 0.95, 0.95, 0.25);<br>
        cairo_pattern_add_color_stop_rgba(pat, 0.7757, 0.98, 0.98, 0.98, 0.125);<br>
        cairo_pattern_add_color_stop_rgba(pat, 1.0000, 1.00, 1.00, 1.00, 0.00);<br>
<br>
        // Render it<br>
        cairo_set_source(pContext, pat);<br>
<br>
        //// START TIMER ////<br>
        cairo_fill_preserve(pContext);<br>
        //// END TIMER ////<br>
<br>
        cairo_pattern_destroy(pat);<br>
<br>
        // Cleanup<br>
        cairo_surface_destroy(pSurface);<br>
        cairo_destroy(pContext);<br>
}<br>
<br>
<br>
In that test function above, if the code is using<br>
cairo_quartz_surface_create() then the call to cairo_fill_preserve()<br>
takes around 600ms to complete. If you comment out<br>
cairo_quartz_surface_create() and use cairo_image_surface_create()<br>
instead, then the call to cairo_fill_preserve() takes around 2ms to<br>
complete.<br>
<br>
In the case where it renders really slow, it is usually stuck down in<br>
the Pixman code calculating radial gradient \
information.</blockquote><div><br></div><div>My profiling seems to show that the code \
path for the Quartz rendering does not involve Pixman.<br></div><div> \
</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px \
solid rgb(204,204,204);padding-left:1ex">  However, I<br>
would expect that it uses the same Pixman code for the image surface<br>
as it does for the Quartz surface type. Does anyone have any ideas<br>
what could be going wrong here?<br></blockquote><div><br></div><div>Instead of using \
Pixman, cairo-quartz is using the native Quartz radial gradient \
implementation.<br></div><div>The radial gradient implementation in Pixman has been \
tuned quite a lot to achieve high performance.<br> </div><div> </div><blockquote \
class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex"> <br>
This testing was done on an iPod touch 5th generation device (ARM<br>
based processor) using Cairo v1.8.0 and Pixman v0.24.0. I realize this<br>
version of Cairo may be a little old now, is anyone able to test this<br>
function using a newer build to see if it may have already been fixed?<br>
<br>
As I type this I realize it may be helpful to get numbers on an x86<br>
processor. I ran the same function under the iPhone simulator on a<br>
Core i7 MacBook Pro and it produced 74ms for the Quartz surface and<br>
less than 1 millisecond for the image surface. As you can see, the<br>
Quartz surface is still an order of magnitude slower.<br>
<br>
Any ideas?<br></blockquote><div><br>Apparently the main slow-down comes from the \
evaluation of ComputeGradientValue.<br><div>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).<br><br></div><div>As you might have noticed, recently I did not have \
much time to work on cairo.<br></div><div>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.<br> <br></div><div>Andrea<br></div><br> </div><blockquote \
class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex"> <span class=""><font color="#888888">--<br>
cairo mailing list<br>
<a href="mailto:cairo@cairographics.org">cairo@cairographics.org</a><br>
<a href="http://lists.cairographics.org/mailman/listinfo/cairo" \
target="_blank">http://lists.cairographics.org/mailman/listinfo/cairo</a><br> \
</font></span></blockquote></div><br></div></div>



-- 
cairo mailing list
cairo@cairographics.org
http://lists.cairographics.org/mailman/listinfo/cairo

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic