]> Pileus Git - ~andy/gtk/blob - gdk/gdkframehistory.c
2f7147ef73253aa61be3773853bdd9b7b5c45e5b
[~andy/gtk] / gdk / gdkframehistory.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2012 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include "gdkframehistory.h"
21 #include "gdkinternals.h"
22
23 #define FRAME_HISTORY_MAX_LENGTH 16
24
25 struct _GdkFrameHistory
26 {
27   GObject parent_instance;
28
29   gint64 frame_counter;
30   gint n_timings;
31   gint current;
32   GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
33 };
34
35 struct _GdkFrameHistoryClass
36 {
37   GObjectClass parent_class;
38 };
39
40 G_DEFINE_TYPE (GdkFrameHistory, gdk_frame_history, G_TYPE_OBJECT)
41
42 static void
43 gdk_frame_history_finalize (GObject *object)
44 {
45   GdkFrameHistory *history = GDK_FRAME_HISTORY (object);
46   int i;
47
48   for (i = 0; i < FRAME_HISTORY_MAX_LENGTH; i++)
49     if (history->timings[i] != 0)
50       gdk_frame_timings_unref (history->timings[i]);
51
52   G_OBJECT_CLASS (gdk_frame_history_parent_class)->finalize (object);
53 }
54
55 static void
56 gdk_frame_history_class_init (GdkFrameHistoryClass *klass)
57 {
58   GObjectClass *object_class = G_OBJECT_CLASS (klass);
59
60   object_class->finalize = gdk_frame_history_finalize;
61 }
62
63 static void
64 gdk_frame_history_init (GdkFrameHistory *history)
65 {
66   history->frame_counter = -1;
67   history->current = FRAME_HISTORY_MAX_LENGTH - 1;
68 }
69
70 GdkFrameHistory *
71 gdk_frame_history_new (void)
72 {
73   return g_object_new (GDK_TYPE_FRAME_HISTORY, NULL);
74 }
75
76 gint64
77 gdk_frame_history_get_frame_counter (GdkFrameHistory *history)
78 {
79   g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), 0);
80
81   return history->frame_counter;
82 }
83
84 gint64
85 gdk_frame_history_get_start (GdkFrameHistory *history)
86 {
87   g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), 0);
88
89   return history->frame_counter + 1 - history->n_timings;
90 }
91
92 void
93 gdk_frame_history_begin_frame (GdkFrameHistory *history)
94 {
95   g_return_if_fail (GDK_IS_FRAME_HISTORY (history));
96
97   history->frame_counter++;
98   history->current = (history->current + 1) % FRAME_HISTORY_MAX_LENGTH;
99
100   if (history->n_timings < FRAME_HISTORY_MAX_LENGTH)
101     history->n_timings++;
102   else
103     {
104       gdk_frame_timings_unref(history->timings[history->current]);
105     }
106
107   history->timings[history->current] = gdk_frame_timings_new (history->frame_counter);
108 }
109
110 GdkFrameTimings *
111 gdk_frame_history_get_timings (GdkFrameHistory *history,
112                                gint64           frame_counter)
113 {
114   gint pos;
115
116   g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), NULL);
117
118   if (frame_counter > history->frame_counter)
119     return NULL;
120
121   if (frame_counter <= history->frame_counter - history->n_timings)
122     return NULL;
123
124   pos = (history->current - (history->frame_counter - frame_counter) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH;
125
126   return history->timings[pos];
127 }
128
129 GdkFrameTimings *
130 gdk_frame_history_get_last_complete (GdkFrameHistory *history)
131 {
132   gint i;
133
134   g_return_val_if_fail (GDK_IS_FRAME_HISTORY (history), NULL);
135
136   for (i = 0; i < history->n_timings; i++)
137     {
138       gint pos = ((history->current - i) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH;
139       if (gdk_frame_timings_get_complete (history->timings[pos]))
140         return history->timings[pos];
141     }
142
143   return NULL;
144 }
145
146 #ifdef G_ENABLE_DEBUG
147 void
148 _gdk_frame_history_debug_print (GdkFrameHistory *history,
149                                 GdkFrameTimings *timings)
150 {
151   gint64 frame_counter = gdk_frame_timings_get_frame_counter (timings);
152   gint64 layout_start_time = _gdk_frame_timings_get_layout_start_time (timings);
153   gint64 paint_start_time = _gdk_frame_timings_get_paint_start_time (timings);
154   gint64 frame_end_time = _gdk_frame_timings_get_frame_end_time (timings);
155   gint64 frame_time = gdk_frame_timings_get_frame_time (timings);
156   gint64 presentation_time = gdk_frame_timings_get_presentation_time (timings);
157   gint64 predicted_presentation_time = gdk_frame_timings_get_predicted_presentation_time (timings);
158   gint64 refresh_interval = gdk_frame_timings_get_refresh_interval (timings);
159   gint64 previous_frame_time = 0;
160   gboolean slept_before = gdk_frame_timings_get_slept_before (timings);
161   GdkFrameTimings *previous_timings = gdk_frame_history_get_timings (history,
162                                                                      frame_counter - 1);
163
164   if (previous_timings != NULL)
165     previous_frame_time = gdk_frame_timings_get_frame_time (previous_timings);
166
167   g_print ("%5" G_GINT64_FORMAT ":", frame_counter);
168   if (previous_frame_time != 0)
169     {
170       g_print (" interval=%-4.1f", (frame_time - previous_frame_time) / 1000.);
171       g_print (slept_before ?  " (sleep)" : "        ");
172     }
173   if (layout_start_time != 0)
174     g_print (" layout_start=%-4.1f", (layout_start_time - frame_time) / 1000.);
175   if (paint_start_time != 0)
176     g_print (" paint_start=%-4.1f", (paint_start_time - frame_time) / 1000.);
177   if (frame_end_time != 0)
178     g_print (" frame_end=%-4.1f", (frame_end_time - frame_time) / 1000.);
179   if (presentation_time != 0)
180     g_print (" present=%-4.1f", (presentation_time - frame_time) / 1000.);
181   if (predicted_presentation_time != 0)
182     g_print (" predicted=%-4.1f", (predicted_presentation_time - frame_time) / 1000.);
183   if (refresh_interval != 0)
184     g_print (" refresh_interval=%-4.1f", refresh_interval / 1000.);
185   g_print ("\n");
186 }
187 #endif /* G_ENABLE_DEBUG */