From: Owen W. Taylor Date: Wed, 14 Nov 2012 17:49:06 +0000 (-0500) Subject: Add GdkFrameHistory and GdkFrameTimings, handle _NET_WM_FRAME_TIMINGS X-Git-Url: http://pileus.org/git/?p=~andy%2Fgtk;a=commitdiff_plain;h=15ee04c66f0e0d34106eb12e815b5f8f2a2b3c5f 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 --- diff --git a/gdk/Makefile.am b/gdk/Makefile.am index a265bcaf1..61aeb4bc7 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -75,6 +75,8 @@ gdk_public_h_sources = \ gdkdisplaymanager.h \ gdkdnd.h \ gdkevents.h \ + gdkframehistory.h \ + gdkframetimings.h \ gdkkeys.h \ gdkkeysyms.h \ gdkkeysyms-compat.h \ @@ -123,6 +125,8 @@ gdk_c_sources = \ gdkdisplaymanager.c \ gdkdnd.c \ gdkevents.c \ + gdkframehistory.c \ + gdkframetimings.c \ gdkglobals.c \ gdkkeys.c \ gdkkeyuni.c \ diff --git a/gdk/gdkframeclock.c b/gdk/gdkframeclock.c index 8c6d20210..ecb84bd8a 100644 --- a/gdk/gdkframeclock.c +++ b/gdk/gdkframeclock.c @@ -304,6 +304,23 @@ gdk_frame_clock_thaw (GdkFrameClock *clock) GDK_FRAME_CLOCK_GET_IFACE (clock)->thaw (clock); } +/** + * gdk_frame_clock_get_history: + * @clock: the clock + * + * Gets the #GdkFrameHistory for the frame clock. + * + * Since: 3.8 + * Return value: (transfer none): the frame history object + */ +GdkFrameHistory * +gdk_frame_clock_get_history (GdkFrameClock *clock) +{ + g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), NULL); + + return GDK_FRAME_CLOCK_GET_IFACE (clock)->get_history (clock); +} + /** * gdk_frame_clock_get_requested: * @clock: the clock diff --git a/gdk/gdkframeclock.h b/gdk/gdkframeclock.h index d75fce984..03b04304c 100644 --- a/gdk/gdkframeclock.h +++ b/gdk/gdkframeclock.h @@ -31,7 +31,7 @@ #ifndef __GDK_FRAME_CLOCK_H__ #define __GDK_FRAME_CLOCK_H__ -#include +#include G_BEGIN_DECLS @@ -87,6 +87,8 @@ struct _GdkFrameClockInterface void (* freeze) (GdkFrameClock *clock); void (* thaw) (GdkFrameClock *clock); + GdkFrameHistory * (* get_history) (GdkFrameClock *clock); + /* signals */ /* void (* frame_requested) (GdkFrameClock *clock); */ /* void (* flush_events) (GdkFrameClock *clock); */ @@ -109,6 +111,8 @@ GdkFrameClockPhase gdk_frame_clock_get_requested (GdkFrameClock *clock); void gdk_frame_clock_freeze (GdkFrameClock *clock); void gdk_frame_clock_thaw (GdkFrameClock *clock); +GdkFrameHistory *gdk_frame_clock_get_history (GdkFrameClock *clock); + /* Convenience API */ void gdk_frame_clock_get_frame_time_val (GdkFrameClock *clock, GTimeVal *timeval); diff --git a/gdk/gdkframeclockidle.c b/gdk/gdkframeclockidle.c index c8a90368a..00d284c03 100644 --- a/gdk/gdkframeclockidle.c +++ b/gdk/gdkframeclockidle.c @@ -33,6 +33,7 @@ struct _GdkFrameClockIdlePrivate { + GdkFrameHistory *history; GTimer *timer; /* timer_base is used to avoid ever going backward */ guint64 timer_base; @@ -77,6 +78,7 @@ gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle) GdkFrameClockIdlePrivate); priv = frame_clock_idle->priv; + priv->history = gdk_frame_history_new (); priv->timer = g_timer_new (); priv->freeze_count = 0; } @@ -229,7 +231,14 @@ gdk_frame_clock_paint_idle (void *data) case GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT: if (priv->freeze_count == 0) { + GdkFrameTimings *timings; + gint64 frame_counter; + priv->frame_time = compute_frame_time (clock_idle); + gdk_frame_history_begin_frame (priv->history); + frame_counter = gdk_frame_history_get_frame_counter (priv->history); + timings = gdk_frame_history_get_timings (priv->history, frame_counter); + gdk_frame_timings_set_frame_time (timings, priv->frame_time); priv->phase = GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT; @@ -370,6 +379,15 @@ gdk_frame_clock_idle_thaw (GdkFrameClock *clock) } } +static GdkFrameHistory * +gdk_frame_clock_idle_get_history (GdkFrameClock *clock) +{ + GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock); + GdkFrameClockIdlePrivate *priv = clock_idle->priv; + + return priv->history; +} + static void gdk_frame_clock_idle_interface_init (GdkFrameClockInterface *iface) { @@ -378,6 +396,7 @@ gdk_frame_clock_idle_interface_init (GdkFrameClockInterface *iface) iface->get_requested = gdk_frame_clock_idle_get_requested; iface->freeze = gdk_frame_clock_idle_freeze; iface->thaw = gdk_frame_clock_idle_thaw; + iface->get_history = gdk_frame_clock_idle_get_history; } GdkFrameClock * diff --git a/gdk/gdkframehistory.c b/gdk/gdkframehistory.c new file mode 100644 index 000000000..e993e5e3f --- /dev/null +++ b/gdk/gdkframehistory.c @@ -0,0 +1,143 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gdkframehistory.h" + +#define FRAME_HISTORY_MAX_LENGTH 16 + +struct _GdkFrameHistory +{ + GObject parent_instance; + + gint64 frame_counter; + gint n_timings; + gint current; + GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH]; +}; + +struct _GdkFrameHistoryClass +{ + GObjectClass parent_class; +}; + +G_DEFINE_TYPE (GdkFrameHistory, gdk_frame_history, G_TYPE_OBJECT) + +static void +gdk_frame_history_finalize (GObject *object) +{ + GdkFrameHistory *history = GDK_FRAME_HISTORY (object); + int i; + + for (i = 0; i < FRAME_HISTORY_MAX_LENGTH; i++) + if (history->timings[i] != 0) + gdk_frame_timings_unref (history->timings[i]); + + G_OBJECT_CLASS (gdk_frame_history_parent_class)->finalize (object); +} + +static void +gdk_frame_history_class_init (GdkFrameHistoryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gdk_frame_history_finalize; +} + +static void +gdk_frame_history_init (GdkFrameHistory *history) +{ + history->frame_counter = -1; + history->current = FRAME_HISTORY_MAX_LENGTH - 1; +} + +GdkFrameHistory * +gdk_frame_history_new (void) +{ + return g_object_new (GDK_TYPE_FRAME_HISTORY, NULL); +} + +gint64 +gdk_frame_history_get_frame_counter (GdkFrameHistory *history) +{ + g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), 0); + + return history->frame_counter; +} + +gint64 +gdk_frame_history_get_start (GdkFrameHistory *history) +{ + g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), 0); + + return history->frame_counter + 1 - history->n_timings; +} + +void +gdk_frame_history_begin_frame (GdkFrameHistory *history) +{ + g_return_if_fail (GDK_IS_FRAME_HISTORY (history)); + + history->frame_counter++; + history->current = (history->current + 1) % FRAME_HISTORY_MAX_LENGTH; + + if (history->n_timings < FRAME_HISTORY_MAX_LENGTH) + history->n_timings++; + else + { + gdk_frame_timings_unref(history->timings[history->current]); + } + + history->timings[history->current] = gdk_frame_timings_new (history->frame_counter); +} + +GdkFrameTimings * +gdk_frame_history_get_timings (GdkFrameHistory *history, + gint64 frame_counter) +{ + gint pos; + + g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), NULL); + + if (frame_counter > history->frame_counter) + return NULL; + + if (frame_counter <= history->frame_counter - history->n_timings) + return NULL; + + pos = (history->current - (history->frame_counter - frame_counter) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH; + + return history->timings[pos]; +} + +GdkFrameTimings * +gdk_frame_history_get_last_complete (GdkFrameHistory *history) +{ + gint i; + + g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), NULL); + + for (i = 0; i < history->n_timings; i++) + { + gint pos = ((history->current - i) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH; + if (gdk_frame_timings_get_complete (history->timings[pos])) + return history->timings[pos]; + } + + return NULL; +} diff --git a/gdk/gdkframehistory.h b/gdk/gdkframehistory.h new file mode 100644 index 000000000..56e9db9c0 --- /dev/null +++ b/gdk/gdkframehistory.h @@ -0,0 +1,49 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GDK_FRAME_HISTORY_H__ +#define __GDK_FRAME_HISTORY_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GdkFrameHistory GdkFrameHistory; +typedef struct _GdkFrameHistoryClass GdkFrameHistoryClass; + +#define GDK_TYPE_FRAME_HISTORY (gdk_frame_history_get_type ()) +#define GDK_FRAME_HISTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_FRAME_HISTORY, GdkFrameHistory)) +#define GDK_IS_FRAME_HISTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_FRAME_HISTORY)) + +GType gdk_frame_history_get_type (void) G_GNUC_CONST; + +GdkFrameHistory *gdk_frame_history_new (void); + +gint64 gdk_frame_history_get_frame_counter (GdkFrameHistory *history); +gint64 gdk_frame_history_get_start (GdkFrameHistory *history); +void gdk_frame_history_begin_frame (GdkFrameHistory *history); +GdkFrameTimings *gdk_frame_history_get_timings (GdkFrameHistory *history, + gint64 frame_counter); +GdkFrameTimings *gdk_frame_history_get_last_complete (GdkFrameHistory *history); + +G_END_DECLS + +#endif /* __GDK_FRAME_HISTORY_H__ */ diff --git a/gdk/gdkframetimings.c b/gdk/gdkframetimings.c new file mode 100644 index 000000000..d9354ede4 --- /dev/null +++ b/gdk/gdkframetimings.c @@ -0,0 +1,180 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gdkframetimings.h" + +struct _GdkFrameTimings +{ + guint ref_count; + + gboolean complete; + gint64 frame_counter; + guint64 cookie; + gint64 frame_time; + gint64 drawn_time; + gint64 presentation_time; + gint64 refresh_interval; +}; + +G_DEFINE_BOXED_TYPE (GdkFrameTimings, gdk_frame_timings, + gdk_frame_timings_ref, + gdk_frame_timings_unref) + +GdkFrameTimings * +gdk_frame_timings_new (gint64 frame_counter) +{ + GdkFrameTimings *timings; + + timings = g_slice_new0 (GdkFrameTimings); + timings->ref_count = 1; + timings->frame_counter = frame_counter; + + return timings; +} + +GdkFrameTimings * +gdk_frame_timings_ref (GdkFrameTimings *timings) +{ + g_return_val_if_fail (timings != NULL, NULL); + + timings->ref_count++; + + return timings; +} + +void +gdk_frame_timings_unref (GdkFrameTimings *timings) +{ + g_return_if_fail (timings != NULL); + g_return_if_fail (timings->ref_count > 0); + + timings->ref_count--; + if (timings->ref_count == 0) + { + g_slice_free (GdkFrameTimings, timings); + } +} + +gint64 +gdk_frame_timings_get_frame_counter (GdkFrameTimings *timings) +{ + return timings->frame_counter; +} + +guint64 +gdk_frame_timings_get_cookie (GdkFrameTimings *timings) +{ + g_return_val_if_fail (timings != NULL, 0); + + return timings->cookie; +} + +void +gdk_frame_timings_set_cookie (GdkFrameTimings *timings, + guint64 cookie) +{ + g_return_if_fail (timings != NULL); + + timings->cookie = cookie; +} + +gboolean +gdk_frame_timings_get_complete (GdkFrameTimings *timings) +{ + g_return_val_if_fail (timings != NULL, FALSE); + + return timings->complete; +} + +void +gdk_frame_timings_set_complete (GdkFrameTimings *timings, + gboolean complete) +{ + g_return_if_fail (timings != NULL); + + timings->complete = complete; +} + +gint64 +gdk_frame_timings_get_frame_time (GdkFrameTimings *timings) +{ + g_return_val_if_fail (timings != NULL, 0); + + return timings->frame_time; +} + +void +gdk_frame_timings_set_frame_time (GdkFrameTimings *timings, + gint64 frame_time) +{ + g_return_if_fail (timings != NULL); + + timings->frame_time = frame_time; +} + +gint64 +gdk_frame_timings_get_drawn_time (GdkFrameTimings *timings) +{ + g_return_val_if_fail (timings != NULL, 0); + + return timings->drawn_time; +} + +void +gdk_frame_timings_set_drawn_time (GdkFrameTimings *timings, + gint64 drawn_time) +{ + g_return_if_fail (timings != NULL); + + timings->drawn_time = drawn_time; +} + +gint64 +gdk_frame_timings_get_presentation_time (GdkFrameTimings *timings) +{ + g_return_val_if_fail (timings != NULL, 0); + + return timings->presentation_time; +} + +void +gdk_frame_timings_set_presentation_time (GdkFrameTimings *timings, + gint64 presentation_time) +{ + g_return_if_fail (timings != NULL); + + timings->presentation_time = presentation_time; +} + +gint64 +gdk_frame_timings_get_refresh_interval (GdkFrameTimings *timings) +{ + g_return_val_if_fail (timings != NULL, 0); + + return timings->refresh_interval; +} + +void +gdk_frame_timings_set_refresh_interval (GdkFrameTimings *timings, + gint64 refresh_interval) +{ + g_return_if_fail (timings != NULL); + + timings->refresh_interval = refresh_interval; +} diff --git a/gdk/gdkframetimings.h b/gdk/gdkframetimings.h new file mode 100644 index 000000000..7fddbd4a6 --- /dev/null +++ b/gdk/gdkframetimings.h @@ -0,0 +1,63 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GDK_FRAME_TIMINGS_H__ +#define __GDK_FRAME_TIMINGS_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GdkFrameTimings GdkFrameTimings; + +GType gdk_frame_timings_get_type (void) G_GNUC_CONST; + +GdkFrameTimings *gdk_frame_timings_new (gint64 frame_counter); + +GdkFrameTimings *gdk_frame_timings_ref (GdkFrameTimings *timings); +void gdk_frame_timings_unref (GdkFrameTimings *timings); + +gint64 gdk_frame_timings_get_frame_counter (GdkFrameTimings *timings); + +guint64 gdk_frame_timings_get_cookie (GdkFrameTimings *timings); +void gdk_frame_timings_set_cookie (GdkFrameTimings *timings, + guint64 cookie); + +gboolean gdk_frame_timings_get_complete (GdkFrameTimings *timings); +void gdk_frame_timings_set_complete (GdkFrameTimings *timings, + gboolean complete); + +gint64 gdk_frame_timings_get_frame_time (GdkFrameTimings *timings); +void gdk_frame_timings_set_frame_time (GdkFrameTimings *timings, + gint64 frame_time); +gint64 gdk_frame_timings_get_drawn_time (GdkFrameTimings *timings); +void gdk_frame_timings_set_drawn_time (GdkFrameTimings *timings, + gint64 frame_time); +gint64 gdk_frame_timings_get_presentation_time (GdkFrameTimings *timings); +void gdk_frame_timings_set_presentation_time (GdkFrameTimings *timings, + gint64 presentation_time); +gint64 gdk_frame_timings_get_refresh_interval (GdkFrameTimings *timings); +void gdk_frame_timings_set_refresh_interval (GdkFrameTimings *timings, + gint64 refresh_interval); + +G_END_DECLS + +#endif /* __GDK_FRAME_TIMINGS_H__ */ diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 4e28f74ec..ae4aaafb0 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -1056,6 +1056,26 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, return return_val; } +static GdkFrameTimings * +find_frame_timings (GdkFrameClock *clock, + guint64 serial) +{ + GdkFrameHistory *history = gdk_frame_clock_get_history (clock); + gint64 start_frame, end_frame, i; + + start_frame = gdk_frame_history_get_start (history); + end_frame = gdk_frame_history_get_frame_counter (history); + for (i = end_frame; i >= start_frame; i--) + { + GdkFrameTimings *timings = gdk_frame_history_get_timings (history, i); + + if (gdk_frame_timings_get_cookie (timings) == serial) + return timings; + } + + return NULL; +} + GdkFilterReturn _gdk_wm_protocols_filter (GdkXEvent *xev, GdkEvent *event, @@ -1074,6 +1094,71 @@ _gdk_wm_protocols_filter (GdkXEvent *xev, display = GDK_WINDOW_DISPLAY (win); + /* This isn't actually WM_PROTOCOLS because that wouldn't leave enough space + * in the message for everything that gets stuffed in */ + if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_DRAWN")) + { + GdkWindowImplX11 *window_impl; + window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl); + if (window_impl->toplevel) + { + guint32 d0 = xevent->xclient.data.l[0]; + guint32 d1 = xevent->xclient.data.l[1]; + guint32 d2 = xevent->xclient.data.l[2]; + guint32 d3 = xevent->xclient.data.l[3]; + + guint64 serial = ((guint64)d0 << 32) | d1; + + GdkFrameClock *clock = gdk_window_get_frame_clock (event->any.window); + GdkFrameTimings *timings = find_frame_timings (clock, serial); + + if (timings) + gdk_frame_timings_set_drawn_time (timings, ((guint64)d2 << 32) | d3); + + if (window_impl->toplevel->frame_pending) + { + window_impl->toplevel->frame_pending = FALSE; + gdk_frame_clock_thaw (clock); + } + } + + return GDK_FILTER_REMOVE; + } + + if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_TIMINGS")) + { + GdkWindowImplX11 *window_impl; + window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl); + if (window_impl->toplevel) + { + guint32 d0 = xevent->xclient.data.l[0]; + guint32 d1 = xevent->xclient.data.l[1]; + guint32 d2 = xevent->xclient.data.l[2]; + guint32 d3 = xevent->xclient.data.l[3]; + + guint64 serial = ((guint64)d0 << 32) | d1; + + GdkFrameClock *clock = gdk_window_get_frame_clock (event->any.window); + GdkFrameTimings *timings = find_frame_timings (clock, serial); + + if (timings) + { + gint64 drawn_time = gdk_frame_timings_get_drawn_time (timings); + gint32 presentation_time_offset = (gint32)d2; + gint32 refresh_interval = d3; + + if (drawn_time && presentation_time_offset) + gdk_frame_timings_set_presentation_time (timings, + drawn_time + presentation_time_offset); + + if (refresh_interval) + gdk_frame_timings_set_refresh_interval (timings, refresh_interval); + + gdk_frame_timings_set_complete (timings, TRUE); + } + } + } + if (xevent->xclient.message_type != gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS")) return GDK_FILTER_CONTINUE; @@ -1145,21 +1230,6 @@ _gdk_wm_protocols_filter (GdkXEvent *xev, return GDK_FILTER_REMOVE; } - else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_DRAWN")) - { - GdkWindowImplX11 *window_impl; - - window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl); - if (window_impl->toplevel && - window_impl->toplevel->frame_pending) - { - window_impl->toplevel->frame_pending = FALSE; - gdk_frame_clock_thaw (gdk_window_get_frame_clock (event->any.window)); - } - - return GDK_FILTER_REMOVE; - } - return GDK_FILTER_CONTINUE; } diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index f2c5735e7..874db0a80 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -853,7 +853,17 @@ static void on_frame_clock_after_paint (GdkFrameClock *clock, GdkWindow *window) { + GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); + GdkFrameHistory *history = gdk_frame_clock_get_history (clock); + gint64 frame_counter = gdk_frame_history_get_frame_counter (history); + GdkFrameTimings *timings = gdk_frame_history_get_timings (history, frame_counter); + gdk_x11_window_end_frame (window); + + if (toplevel->frame_pending) + gdk_frame_timings_set_cookie (timings, toplevel->current_counter_value); + else + gdk_frame_timings_set_complete (timings, TRUE); } void