Re: Freezing updates for compositing managers

View: New views
1 Messages — Rating Filter:   Alert me  

Re: Freezing updates for compositing managers

by Gordon Williams-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Owen + Denis,
        Me and some of the people at Collabora have been looking at the
feasibility of implementing some kind of freeze of updates with Gtk too,
in order to try and reduce tearing artefacts that we are getting in
the compositor.
        I guess in order to eradicate artefacts, you really need two-way
communication between Gtk and the window manager as you say - as even if
the compositor draws after a complete frame, there is no guarantee that
the window hasn't started rendering the next frame and damaged the contents
of the window.
        Even if there is a 'WAIT_FOR_COMPOSITOR' signalling mechanism,
it could prove problematic to implement in Gtk when functions like
gdk_window_scroll are expected not to block and yet to scroll the window
contents immediately (however perhaps this could be postponed?).
        If we don't wait in Gtk, most likely drawing operations on the
window will be locked while the window is composited (and the compositor
will have to wait for the current drawing operation on the window to
finish). At least this seems to be the case for us. With multiple
windows this can end up stalling the window manager quite seriously,
as it waits for each window in turn.
        One possible solution which would allow good performance
without blocking would be to create extra pixmaps to perform triple
buffering using the windowless Gtk branch.

It is probably too much work, but it might be worth considering, given
the advantages?

It could work something like this:

* The window manager adds two window properties, PIXMAP_A and PIXMAP_B,
  containing the IDs of two pixmaps.
* Gtk detects this and writes a property, PIXMAP_WRITING (which is either
  A,B or W(for the window). This tells the window manager where the window
  is currently writing to.
* After it has finished a frame, the window sets PIXMAP_READY to
  whatever PIXMAP_WRITING was (to signal a frame is drawn to the compositor)
  and then chooses a new destination for PIXMAP_WRITING.
* The window manager detects the change of PIXMAP_READY, then sets
  PIXMAP_READING=PIXMAP_READY and composits using this pixmap. Damage
  events would need to be created specially when rendering to one
  of the two pixmaps.
* In the mean time, the next time the window finishes rendering a frame,
  it sets PIXMAP_READY=PIXMAP_WRITING, and then chooses whichever of A,B
  or W is not specified in PIXMAP_READY or PIXMAP_READING.

        I believe this would work without any race conditions, however
there are definitely quite a few issues here.

Bad:
* Memory usage - however there would be no need for the current double
  buffering in Gtk, so I suppose at least only one extra buffer is used,
  and we do save the overhead of allocating new pixmaps each frame.
* Because there are 3 windows to render to, Gtk's exposed area would have to
  be the sum of the previous 2 exposed areas (or the previous two exposed
  areas would have to be copied from PIXMAP_READY). In a lot of cases
  (scrolling) this would not be any worse than doing the panning operation
  I guess, but lots of small updates in different areas could be slower.
* Overly ambitious? I have no idea of the internals of the windowless
  branch. It could be relatively easy, or it could be extremely painful.

Good:
* Performance would be a lot better due to the non-blocking I imagine.
* There would be no need for double buffering in Gtk and hence no blitting of
  the final image, and no allocation of damage-sized pixmaps for every frame
 - which would be a decent performance boost.
* Hopefully no flicker whatsoever

Any thoughts? This is probably a fair chunk of work, but I don't see many
other ways of getting rid of tearing completely. Proper double buffering
(flipping buffers, not Gtk's blitting) could be possible if memory usage
were a problem, but that might cause more problems with synchronisation?

- Gordon
       

-----------------------------

On Mon, 2009-06-29 at 10:10 +0200, Denis Dzyubenko wrote:

> Hi Owen,
>
> Owen Taylor wrote:
> > Fixing this really requires application intervention - when the
> > compositor receives the MapNotify for the window the window might
> > have drawn yet, or might not, and there's no way that the
> > compositor can know.
> >
> > This is actually a symptom of a more general situation - an
> > application wants to make multiple X requests (here a map and
> > then the redraw) and not have the compositor draw until it is done.
> >
> > Thinking of it that way - that gives a pretty straightforward
> > solution - the app can set a property that says "don't update me" -
> > say _NET_WM_FREEZE_UPDATES - and then remove it when it is ready
> > to be painted again.
>
> Sounds like an excellent idea, however it also sounds similar to
> something that the wm-spec already have - can we use the existing
> _NET_WM_SYNC_REQUEST protocol for that? Since compositing manager might
> already support it, it could be pretty straightforward to implement the
> same protocol for the case when a client window is initially mapped. For
> example, when the compositor receives the MapNotify, it might send the
> _NET_WM_SYNC_REQUEST client message and delay showing the window until
> the client responds by setting a _NET_WM_SYNC_REQUEST_COUNTER.

I was originally going to respond and say "it sounds related, but it
isn't related."

But then I had an idea. You can't really use _NET_WM_SYNC_REQUEST
unmodified - it's inherently initiated from the window manager and not
from the client. And this needs to be initiated from the client. (*)

But what if we turned _NET_WM_SYNC_REQUEST_COUNTER into a more
general frame counter. With the following handling:

 - When the client starts drawing a frame, it increments the counter to
   an odd value to freeze updates.
 - When the client finishes drawing, it increments the counter to an
   even value to thaw updates.
 - When the window manager wants to do a sync, it picks an even value
   at least a 100 [arbitrary] values ahead of the last value it
   received from the client and sends _NET_WM_SYNC_REQUEST to the
   client with that value. The client then uses that value on the
   frame completion after processing the resize.

Advantages of this:

 - It has the same race-condition-free-startup and no-round-trip on
   updates as my proposal.

 - It integrates with the sync request system in an aesthetically
   pleasing fashion.

 - It has a very useful extension:

    After redrawing a frame, the window manager sends a
    _NET_WM_FRAME_REDRAWN client message to all clients updating
    the frame counter since the last redraw. The message contains
    the frame value (and maybe some timing information.)

   Voila: properly throttled application updates in a composited
   environment.

Disadvantages of this:

 - Compatibility is tricky; if the window manager is expecting the
   old _NET_WM_SYNC_REQUEST_COUNTER behavior, spontaneous client
   updates will break the WM's use of _NET_WM_SYNC_REQUEST as far
   as I can tell.

   Having the client adapt its behavior is tricky because:

    - Switching between compositing managers and window managers
      in the fly.
    - The possibility of a standalone compositor that wants the
      frame counter with an old window manager that expects the
      old sync counter behavior.

   So, I don't really see how to avoid having the application expose
   two separate counters. [ Applications could, of course, choose to
   only support the new method ... we could deprecate the old way]

 - The Sync extension is not fun to understand and use; it's much
   harder to implement the above as compared to my
   _NET_WM_FREEZE_UPDATES. Toolkits and window managers have however,
   already figured out much of this to handle _NET_WM_SYNC_REQUEST.

- Owen

(*) Even if you accept the extra WM <=> client round trip, I don't
think it works out without toolkit modifications to have the window
manager to spontaneously ask for a sync - it's specified currently
to be tied to a ConfigureNotify. Plus, it doesn't extend to the
other uses cases like atomic frame updates.



_______________________________________________
wm-spec-list mailing list
wm-spec-list@...
http://mail.gnome.org/mailman/listinfo/wm-spec-list