Commit Graph

64 Commits

Author SHA1 Message Date
Owen W. Taylor
515e5f74aa Merge GdkFrameHistory into GdkFrameClock
Now that GdkFrameClock is a  class, not interface, there's no real advantage
to splitting the frame history into an aggregate object, so directly
merge it into GdkFrameClock.
2013-02-14 17:19:52 -05:00
Owen W. Taylor
5f2d1654a5 Change GdkFrameClock from an interface to a class
It's unlikely that anyone will want to have, say, a GtkWidget that
also acts as a GdkFrameClock, so an abstract base class is as
flexible as making GdkFrameClock an interface, but has advantages:

 - If we decide to never make implementing your own frame clock
   possible, we can remove the virtualization.
 - We can put functionality like history into the base class.
 - Avoids the oddity of a interface without a public interface
   VTable, which may cause problems for language bindings.
2013-02-14 17:19:52 -05:00
Owen W. Taylor
fb44ea8a85 Add gdk_frame_timings_get_predicted_presentation_time()
For an operation like synchronizing audio to video playback, we need to
be able to predict the time that a frame will be presented. The details
of this depend on the windowing system, so make the backend predict
a presentation time for ::begin-frame and set it on the GdkFrameTimings.

The timing algorithm of GdkFrameClockIdle is adjusted to give predictable
presentation times for frames that are not throttled by the windowing
system.

Helper functions:

 gdk_frame_clock_get_current_frame_timings()
 gdk_frame_clock_get_refresh_info()

are added for operations that would otherwise be needed multiple times
in different locations.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:51 -05:00
Owen W. Taylor
8855bf052d Add GDK_DEBUG=frames
Add a debug option to print out detailed statistics about each frame drawn.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:51 -05:00
Owen W. Taylor
58b5811d03 Add gdk_frame_timings_get/set_slept_before()
Add functions that tell us whether the main loop slept before we drew
a frame. Blocking with the frame clock frozen doesn't count as sleeping.
We'll use this to advertise to the compositor whether we
are drawing as fast as possible (and it should do the same) or timing
frames carefully (and it should do the same.)

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:50 -05:00
Owen W. Taylor
dc6dedab4d GdkFrameClockIdle: don't start the tiemout/idle when in a frame
Don't start the idle if we're in the middle of painting a frame -
this will prevent us from getting the timing right when starting
the idle after the frame.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:50 -05:00
Owen W. Taylor
15ee04c66f Add GdkFrameHistory and GdkFrameTimings, handle _NET_WM_FRAME_TIMINGS
In order to be able to track statistics about how well we are drawing,
and in order to be able to do sophisticated things with frame timing
like predicting per-frame latencies and synchronizing audio with video,
we need to be able to track exactly when previous frames were drawn
to the screen.

Information about each frame is stored in a new GdkFrameTimings object.
A new GdkFrameHistory object is added which keeps a queue of recent
GdkFrameTimings (this is added to avoid further complicating the
implementation of GdkFrameClock.)

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:50 -05:00
Owen W. Taylor
3cef97f10d GdkFrameClock: Reverse order of resume-events and afterpaint
Keeping events paused after the end of a frame put us in a
weird state where we had to process and queue events - so that
we would get the message from the compositor - but not deliver
them. Instead resume events before ending the frame.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:49 -05:00
Owen W. Taylor
a69285da08 Compress motion synchronized with the paint cycle
When we have pending motion events, instead of delivering them
directly, request the new FLUSH_EVENTS phase of the frame clock.
This allows us to compress repeated motion events sent to the
same window.

In the FLUSH_EVENTS phase, which occur at priority GDK_PRIORITY_EVENTS + 1,
we deliver any pending motion events then turn off event delivery
until the end of the next frame. Turning off event delivery means
that we'll reliably paint the compressed motion events even if more
have arrived.

Add a motion-compression test case which demonstrates behavior when
an application takes too long handle motion events. It is unusable
without this patch but behaves fine with the patch.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:49 -05:00
Owen W. Taylor
344a69880a Add an UPDATE phase and GdkFrameClockTarget, use for GtkStyleContext
Switch GtkStyleContext to using GdkFrameClock. To do this, add a new
UPDATE phase to GdkFrameClock.

Add a GdkFrameClockTarget interface with a single set_clock() method,
and use this to deal with the fact that GtkWidget only has a frame
clock when realized.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:48 -05:00
Owen W. Taylor
7dfa412188 GdkFrameClockIdle: add throttling to 60fps
If the backend is throttling paints, then the frame clock will be
frozen at the end of the frame. If not, then we need to add throttling,
so wait until 16ms after the start of the frame before beginning the
next frame.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:48 -05:00
Owen W. Taylor
1824796bfb GdkFrameClock: add freeze/thaw
Add the ability to freeze a frame clock, which pauses its operation,
then thaw it again later to resume.

Initially this is used to implement freezing updates when we are
waiting for ConfigureNotify in response to changing the size of
a toplevel.

We need a per-window clock for this to work properly, so add that
for the X11 backend.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:48 -05:00
Owen W. Taylor
c4545cc5d4 GdkFrameClock: Make the phase explicit when requesting the frame
Instead of having gdk_frame_clock_request_frame() have
gdk_frame_clock_request_phase() where we can say what phase we need.
This allows us to know if we get a frame-request during layout whether
it's just a request for drawing from the layout, or whether another
layout phase is needed.

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:48 -05:00
Owen W. Taylor
77bac0d6ae Add GdkFrameClock
Add an object GdkFrameClock that we associate with a GdkWindow.
This tracks when the window needs to be repainted, and will also
be used for other operations in the future like relayout and
updating animations.

Based on a patch from Havoc Pennington:

 https://mail.gnome.org/archives/gtk-devel-list/2010-October/msg00004.html

https://bugzilla.gnome.org/show_bug.cgi?id=685460
2013-02-14 17:19:47 -05:00