<html>
<head>
<base href="https://bugs.freedesktop.org/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Need to flush twice to detach snapshots"
href="https://bugs.freedesktop.org/show_bug.cgi?id=92455">92455</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Need to flush twice to detach snapshots
</td>
</tr>
<tr>
<th>Product</th>
<td>cairo
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>Other
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>medium
</td>
</tr>
<tr>
<th>Component</th>
<td>xcb backend
</td>
</tr>
<tr>
<th>Assignee</th>
<td>chris@chris-wilson.co.uk
</td>
</tr>
<tr>
<th>Reporter</th>
<td>psychon@znc.in
</td>
</tr>
<tr>
<th>QA Contact</th>
<td>cairo-bugs@cairographics.org
</td>
</tr></table>
<p>
<div>
<pre>Created <span class=""><a href="attachment.cgi?id=118865" name="attach_118865" title="Reproducer">attachment 118865</a> <a href="attachment.cgi?id=118865&action=edit" title="Reproducer">[details]</a></span>
Reproducer
This comes originally from <a href="https://github.com/i3/i3/pull/1990">https://github.com/i3/i3/pull/1990</a>.
The attached test program has the following behavior:
$ gcc -Wall -Wextra test.c $(pkg-config --cflags --libs cairo xcb) && ./a.out
a.out: ../../../../src/cairo-surface.c:1652:
cairo_surface_mark_dirty_rectangle: Assertion `! _cairo_surface_has_snapshots
(surface)' failed.
[1] 11287 abort ./a.out
$ gcc -Wall -Wextra test.c $(pkg-config --cflags --libs cairo xcb)
-DUSE_WORKAROUND && ./a.out
$
This program creates a cairo-xcb surface (in a way so that RENDER is not used),
draws to it (this causes a fallback) and then calls cairo_surface_flush(surf);
cairo_surface_mark_dirty(surf);. As the failed assertion shows, the surface has
snapshots attached during cairo_surface_mark_dirty() which we explicitly
disallow via an assertion.
In the second run, the USE_WORKAROUND preprocessor symbol is defined. The only
difference is that this program now calls cairo_surface_flush() twice in a row
so that the second call can detach the snapshot that the first flush added.
This snapshot is added in _cairo_xcb_surface_flush() and is used to save the
fallback surface for later use.
As far as I can see, this bug always existed. No idea why no one noticed it so
far (well, how many people don't have RENDER?).
@Chris: Why are we detaching snapshots in cairo_surface_flush() anyway?
Wouldn't it make more sense to detach them in cairo_surface_mark_dirty(),
because that's the point when the snapshots become invalid. Changing this would
break _cairo_surface_snapshot(), because it uses a snapshot to do a
copy-on-write, but that might count as misuse of the API. This could in turn be
fixed with some kind of "modification callback chain". What do you think?
Short term, I would just remove the call to _cairo_surface_attach_snapshot()
from _cairo_xcb_surface_flush() to fix the symptom of this problem, but flush()
has (to me) more of a "make my drawing visible"-semantics and not a "I will
definitely draw to things directly now".</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are the QA Contact for the bug.</li>
</ul>
</body>
</html>