[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"><<a \
href="mailto:bobby8934@gmail.com" target="_blank">bobby8934@gmail.com</a>></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(&Matrix, 3.6, 0.0, 0.0, 1.35, 568, 66);<br>
cairo_set_matrix(pContext, &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