[gtk+/wip/frame-synchronization: 836/857] Add GdkFrameHistory and GdkFrameTimings, handle _NET_WM_FRAME_TIMINGS
- From: Owen Taylor <otaylor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/frame-synchronization: 836/857] Add GdkFrameHistory and GdkFrameTimings, handle _NET_WM_FRAME_TIMINGS
- Date: Wed, 13 Feb 2013 06:13:48 +0000 (UTC)
commit c6966f00cef4f58266e8d16227303ab32734e0fc
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Wed Nov 14 12:49:06 2012 -0500
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
gdk/Makefile.am | 4 +
gdk/gdkframeclock.c | 17 +++++
gdk/gdkframeclock.h | 6 ++-
gdk/gdkframeclockidle.c | 19 +++++
gdk/gdkframehistory.c | 143 ++++++++++++++++++++++++++++++++++++
gdk/gdkframehistory.h | 49 +++++++++++++
gdk/gdkframetimings.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++
gdk/gdkframetimings.h | 63 ++++++++++++++++
gdk/x11/gdkdisplay-x11.c | 100 ++++++++++++++++++++++----
gdk/x11/gdkwindow-x11.c | 10 +++
10 files changed, 575 insertions(+), 16 deletions(-)
---
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index a265bca..61aeb4b 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 8c6d202..ecb84bd 100644
--- a/gdk/gdkframeclock.c
+++ b/gdk/gdkframeclock.c
@@ -305,6 +305,23 @@ gdk_frame_clock_thaw (GdkFrameClock *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 d75fce9..03b0430 100644
--- a/gdk/gdkframeclock.h
+++ b/gdk/gdkframeclock.h
@@ -31,7 +31,7 @@
#ifndef __GDK_FRAME_CLOCK_H__
#define __GDK_FRAME_CLOCK_H__
-#include <glib-object.h>
+#include <gdk/gdkframehistory.h>
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 c8a9036..00d284c 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 0000000..e993e5e
--- /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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 0000000..56e9db9
--- /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 <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#ifndef __GDK_FRAME_HISTORY_H__
+#define __GDK_FRAME_HISTORY_H__
+
+#include <gdk/gdkframetimings.h>
+
+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 0000000..d9354ed
--- /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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 0000000..7fddbd4
--- /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 <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#ifndef __GDK_FRAME_TIMINGS_H__
+#define __GDK_FRAME_TIMINGS_H__
+
+#include <glib-object.h>
+
+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 4e28f74..ae4aaaf 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 f2c5735..874db0a 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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]