Bug 84330

Summary: record-paint-alpha-clip-mask.xcb.rgb24 random failure
Product: cairo Reporter: Massimo <sixtysix>
Component: xcb backendAssignee: Uli Schlachter <psychon>
Status: RESOLVED FIXED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium CC: darxus
Version: unspecified   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: quick hack

Description Massimo 2014-09-25 15:47:14 UTC
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.
Comment 1 Darxus 2016-07-15 14:37:35 UTC
*** Bug 96933 has been marked as a duplicate of this bug. ***
Comment 2 Darxus 2016-07-15 14:38:48 UTC
Bug 96933 has a lot of info.

This patch causes the entire xcb target to pass for me (when used with regenerated references).
Comment 3 Uli Schlachter 2016-07-16 08:28:08 UTC
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.)
Comment 4 Darxus 2016-07-16 18:48:10 UTC
Commenting out the "if (ntraps)" line in xserver does not get these tests to pass.

Tested on xserver commit 033888e7766d226a179357d970223428c19c4b53
and cairo commit 190678f6444ad879847d603c3c9eaf8e9ab6887a .
Comment 5 Uli Schlachter 2016-07-17 13:19:24 UTC
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
Comment 6 Uli Schlachter 2016-07-21 17:03:57 UTC
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.