Created attachment 19487 [details] addblur.c convolves with ADD and paint_with_alpha When simulating a blur effect with OPERATOR_ADD and paint_with_alpha(), the pdf backends suffer from extreme slowdown as the number of convolutions is increased compared to the image backend or the PDF backend of cairo-1.2.4. The attached mini program addblur.c illustrates the issue for various backends. The issue affects the svg1.1, ps2, ps3, and the pdf backends at least, but not the svg backend when emitting SVG1.2. The run times below were generated with cairo HEAD at commit 0c777a3e0de0d48289432a3 (similar results can be seen with cairo-1.6.4). After the first few blur levels the times seem to grow exponentially. 0 misc $ time ./addblur pdf 1 real 0m0.376s user 0m0.348s sys 0m0.028s 0 misc $ time ./addblur pdf 2 real 0m0.418s user 0m0.388s sys 0m0.028s 0 misc $ time ./addblur pdf 3 real 0m0.602s user 0m0.528s sys 0m0.072s 0 misc $ time ./addblur pdf 4 real 0m1.334s user 0m1.080s sys 0m0.252s 0 misc $ time ./addblur pdf 5 real 0m4.198s user 0m3.188s sys 0m0.960s 0 misc $ time ./addblur pdf 6 real 0m15.672s user 0m11.957s sys 0m3.712s 0 misc $ time ./addblur pdf 7 real 1m3.895s user 0m47.687s sys 0m15.917s With cairo-1.2.4 the times were much less sensitive to the blur level: 0 misc $ time ./addblur pdf 1 real 0m0.395s user 0m0.336s sys 0m0.028s 0 misc $ time ./addblur pdf 2 real 0m0.371s user 0m0.348s sys 0m0.024s 0 misc $ time ./addblur pdf 3 real 0m0.384s user 0m0.352s sys 0m0.016s 0 misc $ time ./addblur pdf 4 real 0m0.380s user 0m0.364s sys 0m0.012s 0 misc $ time ./addblur pdf 5 real 0m0.400s user 0m0.368s sys 0m0.028s 0 misc $ time ./addblur pdf 6 real 0m0.409s user 0m0.300s sys 0m0.100s 0 misc $ time ./addblur pdf 7 real 0m0.450s user 0m0.400s sys 0m0.020s
In this code you are doing two calls to cairo_paint_with_alpha() then using the output as the source pattern to do another two calls to cairo_paint_with_alpha(). This is repeated for each iteration. When the number of blurs is 1 the following operations are performed: Pattern A is a triangle fill Pattern B is pattern A painted twice Pattern C is pattern B painted twice paint C onto the target surface Due to the use of operators not supported by most vector backends fallback images will be used which requires _cairo_meta_surface_acquire_source_image() to be called. In the image backend acquire_source is called 3 times. In the vector backends acquire_source is called 7 times. When the number of blurs is 2 the following operations are performed: Pattern A is a triangle fill Pattern B is pattern A painted twice Pattern C is pattern B painted twice Pattern D is pattern C painted twice paint D onto the target surface In the image backend acquire_source is called 4 times. In the vector backends _cairo_meta_surface_acquire_source_image() is called 31 times. The problem with the vector backends is a result of the way all the operations are recorded then replayed. The first problem is we do not yet have copy-on-write in the meta surface. Every time the same meta surface pattern is painted a copy of the source meta surface is made. The second problem is every time the same pattern is painted, _cairo_meta_surface_acquire_source_image() replays the meta surface to an image surface. All patterns used by this meta surface are also replayed to the image surface. So for num blurs = 2, painting pattern D on the target will result in the following calls to acquire_source: meta surface num calls to acquire source -------------------------------------------- Pattern D 1 Pattern C 2 Pattern B 4 Pattern A 8 The group with the triangle 16 --------- total 31 Fixing this requires two things: - An implementation of copy-on-write for the meta-surface so that we know when we are re-using the same pattern. - Caching the image created by _cairo_meta_surface_acquire_source_image() instead of replaying the meta surface to an image every time _cairo_meta_surface_acquire_source_image() is called. The reason the slow down does not occur in 1.2.4 is that in 1.2.4 the PDF surface does not implement _create_similar. This will cause cairo_surface_create_similar() to return an image surface instead of a meta surface.
meta-surface source snapshotting pushed: commit 7903c80ee81777bab6eec408c10b2b59330b10f7 Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Sat Jul 4 13:50:15 2009 +0100 [meta] Cache replays when used as a pattern source Use the cow-snapshotting mechanism to store the meta surface replay (either to an image inside acquire_source_image() or to a similar surface during clone_similar()). Fixes Bug 17971 -- Extreme slowdown for manual convolutions in most vector backends. https://bugs.freedesktop.org/show_bug.cgi?id=17971
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.