<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>