Re: Horribly slow rendering using Quartz surfaces
Andrea Canciani <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <CAN_5=BBZZYX=m+7y_QPW_Z8rvZXbF2tTzfHyW3fC=LXeA-6bZQ@mail.gmail.com> |
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 <[email protected]> wrote: > 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