After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 685460 - Add frame synchronization to GTK+
Add frame synchronization to GTK+
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
unspecified
Other All
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2012-10-04 02:46 UTC by Owen Taylor
Modified: 2013-12-05 21:54 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
GdkDisplayX11: Don't use substructure events in internal accounting (8.73 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
Add GdkPaintClock (39.98 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
Use GdkPaintClock for relayout (9.49 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
GdkPaintClock: Make the phase explicit when requesting the frame (11.97 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
GdkPaintClock: add freeze/thaw (8.81 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
Switch to an extended form of _NET_WM_SYNC_REQUEST_COUNTER (5.75 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
Use _NET_WM_FRAME_DRAWN to synchronize frame drawing (5.81 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
Freeze the update counter for unmapped windows (1.95 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
GdkWindowX11: start off with an odd frame-counter value (3.01 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
GdkPaintClockIdle: add throttling to 60fps (4.75 KB, patch)
2012-10-04 02:46 UTC, Owen Taylor
none Details | Review
Add an UPDATE phase and GdkPaintClockTarget, use for GtkStyleContext (16.55 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
Add back GtkTimeline (26.25 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
GtkTimeline: remove settable FPS (5.76 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
Hook GtkTimeline up to GdkPaintClock (19.54 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
GtkTimeline: introspection fixes, add :progress-type property (5.50 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
GtkTimeline: Wrap around the progress correctly when looping (1.92 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
Add a test of an animated resizing window (6.73 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
GtkScrolledWindow: use GdkPaintClock for kinetic scrolling (4.59 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review
Compress motion synchronized with the paint cycle (24.68 KB, patch)
2012-10-04 02:47 UTC, Owen Taylor
none Details | Review

Description Owen Taylor 2012-10-04 02:46:18 UTC
I'm filing these patches on a bug for review that way for those who
prefer - they are also in the wip/frame-synchronization branch in git.
Comment 1 Owen Taylor 2012-10-04 02:46:27 UTC
Created attachment 225739 [details] [review]
GdkDisplayX11: Don't use substructure events in internal accounting

We may receive events because SubstructureNotifyMask has been selected
for the root window. (Most likely, this would occur because GTK+
is being used inside a window manager like Metacity or Mutter.)
This can confuse various types of internal accounting, so detect
such events and comprehensively ignore them for GDK's internal
purposes. We still need to generate GDK events for these cases
because you can select for substructure events with
GDK_SUBSTRUCTURE_MASK.
Comment 2 Owen Taylor 2012-10-04 02:46:31 UTC
Created attachment 225740 [details] [review]
Add GdkPaintClock

Add an object GdkPaintClock 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
Comment 3 Owen Taylor 2012-10-04 02:46:34 UTC
Created attachment 225741 [details] [review]
Use GdkPaintClock for relayout

Add a ::layout signal to GdkPaintClock and use it instead of an idle
handler to drive the restyling and relayout of containers.
Comment 4 Owen Taylor 2012-10-04 02:46:37 UTC
Created attachment 225742 [details] [review]
GdkPaintClock: Make the phase explicit when requesting the frame

Instead of having gdk_paint_clock_request_frame() have
gdk_paint_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.
Comment 5 Owen Taylor 2012-10-04 02:46:40 UTC
Created attachment 225743 [details] [review]
GdkPaintClock: add freeze/thaw

Add the ability to freeze a paint 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.
Comment 6 Owen Taylor 2012-10-04 02:46:43 UTC
Created attachment 225744 [details] [review]
Switch to an extended form of _NET_WM_SYNC_REQUEST_COUNTER

By exporting two XSync counters on a toplevel window, we subscribe
to an extended form of the _NET_WM_SYNC_REQUEST_COUNTER protocol,
where the window manager can initiate an atomic frame, as previously,
but the application can also do so by incrementing the new counter to
an odd value, and then to an even value to finish the frame.

See:
https://mail.gnome.org/archives/wm-spec-list/2011-October/msg00006.html

The support for 64-bit integers that GLib requires is used to
simplify the logic.
Comment 7 Owen Taylor 2012-10-04 02:46:46 UTC
Created attachment 225745 [details] [review]
Use _NET_WM_FRAME_DRAWN to synchronize frame drawing

As part of the extended _NET_WM_SYNC_REQUEST_COUNTER protocol,
we get a _NET_WM_FRAME_DRAWN message for each frame we draw. Use this
to synchronize the updates we are doing with the compositing manager's
drawing, and ultimately with with display refresh.

We now set the sync request counters on all windows, including
override-redirect windows, since it is also useful to do synchronized,
atomic updates for such windows.
Comment 8 Owen Taylor 2012-10-04 02:46:49 UTC
Created attachment 225746 [details] [review]
Freeze the update counter for unmapped windows

When a window is unmapped, freeze its paint clock. This avoids doing
unnecessary work, but also means that we won't block waiting for
_NET_WM_FRAME_DRAWN messages that will never be received since the
frame ended while the window was withdrawn.
Comment 9 Owen Taylor 2012-10-04 02:46:53 UTC
Created attachment 225747 [details] [review]
GdkWindowX11: start off with an odd frame-counter value

By starting with an odd frame counter value, we make the mapping
and initial paint of the window an atomic operation, avoiding
any visual artifacts from an unpainted window.

Possible improvement: start the frame when doing gdk_window_show(),
so that the same improvement occurs for windows that were previously
shown and are being mapped again.
Comment 10 Owen Taylor 2012-10-04 02:46:56 UTC
Created attachment 225748 [details] [review]
GdkPaintClockIdle: add throttling to 60fps

If the backend is throttling paints, then the paint 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.
Comment 11 Owen Taylor 2012-10-04 02:47:00 UTC
Created attachment 225749 [details] [review]
Add an UPDATE phase and GdkPaintClockTarget, use for GtkStyleContext

Switch GtkStyleContext to using GdkPaintClock. To do this, add a new
UPDATE phase to GdkPaintClock.

Add a GdkPaintClockTarget interface with a single set_clock() method,
and use this to deal with the fact that GtkWidget only has a paint
clock when realized.
Comment 12 Owen Taylor 2012-10-04 02:47:03 UTC
Created attachment 225750 [details] [review]
Add back GtkTimeline

Add back the GtkTimeline code that previously made private and
then removed. It will be hooked up to GdkPaintClock. This commit
purely adds the old code back.
Comment 13 Owen Taylor 2012-10-04 02:47:07 UTC
Created attachment 225751 [details] [review]
GtkTimeline: remove settable FPS

The frames-per-second for an animation should be controlled by how
fast we can process frames and the the frame-rate of the display; it's not
a meaningful app-settable property.
Comment 14 Owen Taylor 2012-10-04 02:47:11 UTC
Created attachment 225752 [details] [review]
Hook GtkTimeline up to GdkPaintClock

Use GdkPaintClock for the timing of GtkTimeline. This require the
user to provide either a GtkWidget or a GdkPaintClock when creating
the timeline. The default constructor now takes a GtkWidget. If you
want to create a GdkPaintClock without a widget, you need to use
g_object_new() and pass in a GdkPaintClock and GdkScreen.
Comment 15 Owen Taylor 2012-10-04 02:47:14 UTC
Created attachment 225753 [details] [review]
GtkTimeline: introspection fixes, add :progress-type property

Fix up introspection information for GtkTimeline, install the
header has a public heaer, and add the property for :progress-type.
Comment 16 Owen Taylor 2012-10-04 02:47:18 UTC
Created attachment 225754 [details] [review]
GtkTimeline: Wrap around the progress correctly when looping

When we have a looping animation for something like an angle,
we need to make sure that the distance we go past 1.0 becomes
the starting distance for the next frame. This prevents a
stutter at the loop position.
Comment 17 Owen Taylor 2012-10-04 02:47:21 UTC
Created attachment 225755 [details] [review]
Add a test of an animated resizing window

Add a test of a window with an animated size and contents. The
test accepts load factor command line argument to see how things
work as the drawing of the content requires more GPU resources.
Comment 18 Owen Taylor 2012-10-04 02:47:25 UTC
Created attachment 225756 [details] [review]
GtkScrolledWindow: use GdkPaintClock for kinetic scrolling

Use GdkPaintClock when animating scrolling via touch, rather
than a timeout.
Comment 19 Owen Taylor 2012-10-04 02:47:29 UTC
Created attachment 225757 [details] [review]
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 paint 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.
Comment 20 Carlos Garnacho 2012-10-04 13:01:24 UTC
(In reply to comment #19)
> Created an attachment (id=225757) [details] [review]
> Compress motion synchronized with the paint cycle

This patch might bring in subtle issues with multipointer, probably event compression must be maintained per gdk_event_get_device() there
Comment 21 Matthias Clasen 2013-04-29 04:23:01 UTC
I believe this should be closed, since we've gotten it all merged for 3.8
Comment 22 Martin Renold 2013-06-16 13:48:30 UTC
this change causes trouble for painting/drawing apps, see Bug 702392