|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
Re: Freezing updates for compositing managersHi 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 |
| Free embeddable forum powered by Nabble | Forum Help |