Re: Frame synchronization open questions



On Thu, 2012-10-04 at 08:09 -0400, Alexander Larsson wrote:
> > Some open questions in my head about the frame synchronization work:

[...]

> > * For pausing the main event delivery, what we currently do is that
> >   we queue events but don't dispatch them. This could conceivably
> >   cause ordering problems for apps that use filters, or for work
> >   in GDK that is done at the translate stage - since we are not
> >   pausing translation, just pausing delivery. Alternatives:
> 
> Are you sure that is really a problem? The x11 gdk_event_source_check()
> code will never even look for a message if there is any GdkEvent queued.
> And if there is nothing queued _gdk_x11_display_queue_events() will stop
> as soon any X event was converted to a queued GdkEvent. And, since this
> queued event will not be read due to the pause we will never process more
> X events until resume events.

That gets into the details of exactly how I implemented event pausing,
but logically speaking, if event delivery is paused, and a new event
happens, it needs to be queued up in GDK, Xlib, or in the X server.
If we don't translate events, then either:

 * Event is queued in Xlib, XPending() starts returning TRUE
 * Event is queued in XServer, the file descriptor 

Either situation is going to make us start spinning currently. But leaving
that aside, we *need* to translate events or we'll never get _NET_WM_FRAME_DONE
and unfreeze event delivery.

My current preference is to just unfreeze all event delivery at the end of
drawing the frame, and not wait for _NET_WM_FRAME_DONE. Then we can make
pausing *really* pausing - not unqueue, not translate, etc. I don't see
any real disadvantage of doing things that way.

[...]

> What I do however worry about is the combination of multiple GdkPaintClocks
> and gdk_display_set_events_paused(). It seems to me that each paint clock
> assumes it has full ownership of the display, calling set_events_paused(FALSE)
> whenever it has finished its paint cycle. However, could there not be other
> paintclocks (say for another toplevel) being active at that time?

Yes, this is an issue. However, if you switch to the above approach, then all
you have to do is to properly reference count the event-pausing - once we
reach the GDK_PRIORITY_EVENTS + 1 idle, we want to pause *all* event delivery
until we are done with new frame handling.

> Another thing I worry about is offscreen window animation. If you have an window
> with an embedded offscreen inside, then queueing a redraw on a widget inside the
> offscreen will cause a repaint cycle. When drawing to the offscreen this will
> generate damage events that will cause the embedding widget to repaint itself.
> However the damage events will be emitted during the paint phase, and the parent
> widget will not get these until the next frame. This will cause a delay of on frame
> which may look weird.

Hmm. So your concern is that the connection between the embedded
offscreen and the embedder is purely at the GTK+ level - if GDK_DAMAGE
events are not delivered to GTK+, then the the embedder won't know to
repaint.

I think the normal way it would end up working is:

 offscreen paints a frame, damage events are generated
 damage events are delivered, new frame is queued for the embedder

 embedder paints a frame, waits for _NET_WM_FRAME_DONE
 offscreen paints a frame, damage events are generated
 damage events are delivered, new frame is queued for the embedder
 _NET_WM_FRAME_DONE arrives
  
 embedder paints a frame, waits for _NET_WM_FRAME_DONE
 offscreen paints a frame, damage events are generated
 damage events are delivered, new frame is queued for the embedder
 _NET_WM_FRAME_DONE arrives

So the offscreen will generally paint during the wait for
_NET_WM_FRAME_DONE, and immediately get incorporated into the next
output frame. Though once things get loaded down and slow, there is no
guarantee of this.

To do better than this, I think you need to slave the clock for the
offscreen into the clock for the window that is embedding it. If the
size of the embedded widget is free-floating and not constrained by the
allocation of the embedder, then the slave clock would simply do the
complete cycle inside an ::update handler. If you want integration
of size-negotiation, then you'd have to do different phases at different
points in the master clock cycle.

And yes, the delivery of damage as events is problematical for that kind
of slaving - maybe we would need to have a signal on GdkOffscreenWindow
to allow getting as-it-happens notification of damage.

- Owen




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]