Created attachment 106861 [details] quick hack In this test there are a number of cairo_paint_with_alpha calls with a clip composed of two non intersecting paths. In these cases _composite_mask_clip (from src/cairo-xcb-surface-render.c lines 3458) is executed and this function assumes that it is possible to avoid a deferred clear. But this test shows that is not always possible, in fact clearing the surface when info.traps.num_traps == 0, fixes the test for the targets xcb.argb32 and xcb{,-window{,&}}.rgb24 Not clearing a surface leaves it in a status that is possibly clear and that's the reason of the occasional failures.
*** Bug 96933 has been marked as a duplicate of this bug. ***
Bug 96933 has a lot of info. This patch causes the entire xcb target to pass for me (when used with regenerated references).
Sorry that I missed this report for two years. No idea how that happened. Also: sorry, but I think that this might be a bug in the X11 server. _composite_traps() is a wrapper around _cairo_xcb_connection_render_trapezoids() that converts from "cairo" to "X11", so this doesn't do anything special here. So, we are sending a Trapezoids-request with an empty list of traps. Looking at the render spec, a Trapezoids-request with an empty list of traps should just copy the source to the target. I bet some code is incorrectly optimizing this away, assuming it is a no-op (which it would e.g. be for operator OVER or ADD). And indeed, the bug is easy to find: https://cgit.freedesktop.org/xorg/xserver/tree/render/render.c?id=e8e36755abb17872d669b88d33ca9adc511029a0#n745 Does anyone have the time to test if this bug is fixed if the above "if (ntraps)" is just removed? (Afterwards, I guess we should still work around this in cairo, but at least we will also get the Xorg bug fixed and we can have a comment saying why this is needed.)
Commenting out the "if (ntraps)" line in xserver does not get these tests to pass. Tested on xserver commit 033888e7766d226a179357d970223428c19c4b53 and cairo commit 190678f6444ad879847d603c3c9eaf8e9ab6887a .
Ok, I was wrong in that this is a bug in the server. The part that I forgot is: Each render composite operation is only applied to the extents of the affected region. This means that "no trapezoids" means "no extents" means "no effect" and this is indeed a no-op. I don't know if the RENDER spec says that anywhere, but it is how the implementation behaves. The comment in the code indicates this with the comment saying "assert(trap extents == extents)". Obviously (as this bug shows), this assert is wrong. It might even still be wrong when we have a non-empty list of traps. So my proposed fix is to just drop this optimisation completely. I sent the following fix to the cairo mailing list: https://lists.cairographics.org/archives/cairo/2016-July/027619.html
commit 3f8241f48488d3da4afce6646e043ee70cf1cfd2 Author: Uli Schlachter <psychon@znc.in> Date: Sun Jul 17 15:08:51 2016 +0200 cairo-xcb: Remove a wrong optimisation When doing a "complicated" mask operation, we draw the clip to a surface and use this as a mask in later operations. The code assumes that this operation draws to the whole target surface and thus a deferred clear may be skipped. However, this requires that the extents of the trapezoids that will be drawn and the extents of the surface are the same. This assumption is wrong, as can be seen e.g. by the bug report that this commit fixes. The fix is just not to skip the deferred clear. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=84330 Signed-off-by: Uli Schlachter <psychon@znc.in>
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.