<div dir="ltr"><div><div><div><div>On my system, running your code on image 10000 times takes ~ 0.3 seconds, while on a quartz surface it takes about 3 seconds.<br></div>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.<br>
<br></div>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.<br></div>
<br></div>Andrea<br><br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Aug 21, 2013 at 4:40 PM, Andrea Canciani <span dir="ltr"><<a href="mailto:ranma42@gmail.com" target="_blank">ranma42@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="im">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><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5">
<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></div><div>My profiling seems to show that the code path for the Quartz rendering does not involve Pixman.<br></div><div class="im">
<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><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 class="im"><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><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.<span class="HOEnZb"><font color="#888888"><br>
<br></font></span></div><span class="HOEnZb"><font color="#888888"><div>Andrea<br></div><br> </font></span></div><div class="im"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<span><font color="#888888">--<br>
cairo mailing list<br>
<a href="mailto:cairo@cairographics.org" target="_blank">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></div><br></div></div>
</blockquote></div><br></div>