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 <string.h>
21 
22 #include "gdkframeclockprivate.h"
23 
24 /**
25  * SECTION:gdkframetimings
26  * @Short_description: Object holding timing information for a single frame
27  * @Title: Frame timings
28  *
29  * A #GdkFrameTimings object holds timing information for a single frame
30  * of the application’s displays. To retrieve #GdkFrameTimings objects,
31  * use gdk_frame_clock_get_timings() or gdk_frame_clock_get_current_timings().
32  * The information in #GdkFrameTimings is useful for precise synchronization
33  * of video with the event or audio streams, and for measuring
34  * quality metrics for the application’s display, such as latency and jitter.
35  */
36 
G_DEFINE_BOXED_TYPE(GdkFrameTimings,gdk_frame_timings,gdk_frame_timings_ref,gdk_frame_timings_unref)37 G_DEFINE_BOXED_TYPE (GdkFrameTimings, gdk_frame_timings,
38                      gdk_frame_timings_ref,
39                      gdk_frame_timings_unref)
40 
41 GdkFrameTimings *
42 _gdk_frame_timings_new (gint64 frame_counter)
43 {
44   GdkFrameTimings *timings;
45 
46   timings = g_slice_new0 (GdkFrameTimings);
47   timings->ref_count = 1;
48   timings->frame_counter = frame_counter;
49 
50   return timings;
51 }
52 
53 gboolean
_gdk_frame_timings_steal(GdkFrameTimings * timings,gint64 frame_counter)54 _gdk_frame_timings_steal (GdkFrameTimings *timings,
55                           gint64           frame_counter)
56 {
57   if (timings->ref_count == 1)
58     {
59       memset (timings, 0, sizeof *timings);
60       timings->ref_count = 1;
61       timings->frame_counter = frame_counter;
62       return TRUE;
63     }
64 
65   return FALSE;
66 }
67 
68 /**
69  * gdk_frame_timings_ref:
70  * @timings: a #GdkFrameTimings
71  *
72  * Increases the reference count of @timings.
73  *
74  * Returns: @timings
75  * Since: 3.8
76  */
77 GdkFrameTimings *
gdk_frame_timings_ref(GdkFrameTimings * timings)78 gdk_frame_timings_ref (GdkFrameTimings *timings)
79 {
80   g_return_val_if_fail (timings != NULL, NULL);
81 
82   timings->ref_count++;
83 
84   return timings;
85 }
86 
87 /**
88  * gdk_frame_timings_unref:
89  * @timings: a #GdkFrameTimings
90  *
91  * Decreases the reference count of @timings. If @timings
92  * is no longer referenced, it will be freed.
93  *
94  * Since: 3.8
95  */
96 void
gdk_frame_timings_unref(GdkFrameTimings * timings)97 gdk_frame_timings_unref (GdkFrameTimings *timings)
98 {
99   g_return_if_fail (timings != NULL);
100   g_return_if_fail (timings->ref_count > 0);
101 
102   timings->ref_count--;
103   if (timings->ref_count == 0)
104     {
105       g_slice_free (GdkFrameTimings, timings);
106     }
107 }
108 
109 /**
110  * gdk_frame_timings_get_frame_counter:
111  * @timings: a #GdkFrameTimings
112  *
113  * Gets the frame counter value of the #GdkFrameClock when this
114  * this frame was drawn.
115  *
116  * Returns: the frame counter value for this frame
117  * Since: 3.8
118  */
119 gint64
gdk_frame_timings_get_frame_counter(GdkFrameTimings * timings)120 gdk_frame_timings_get_frame_counter (GdkFrameTimings *timings)
121 {
122   return timings->frame_counter;
123 }
124 
125 /**
126  * gdk_frame_timings_get_complete:
127  * @timings: a #GdkFrameTimings
128  *
129  * The timing information in a #GdkFrameTimings is filled in
130  * incrementally as the frame as drawn and passed off to the
131  * window system for processing and display to the user. The
132  * accessor functions for #GdkFrameTimings can return 0 to
133  * indicate an unavailable value for two reasons: either because
134  * the information is not yet available, or because it isn't
135  * available at all. Once gdk_frame_timings_get_complete() returns
136  * %TRUE for a frame, you can be certain that no further values
137  * will become available and be stored in the #GdkFrameTimings.
138  *
139  * Returns: %TRUE if all information that will be available
140  *  for the frame has been filled in.
141  * Since: 3.8
142  */
143 gboolean
gdk_frame_timings_get_complete(GdkFrameTimings * timings)144 gdk_frame_timings_get_complete (GdkFrameTimings *timings)
145 {
146   g_return_val_if_fail (timings != NULL, FALSE);
147 
148   return timings->complete;
149 }
150 
151 /**
152  * gdk_frame_timings_get_frame_time:
153  * @timings: A #GdkFrameTimings
154  *
155  * Returns the frame time for the frame. This is the time value
156  * that is typically used to time animations for the frame. See
157  * gdk_frame_clock_get_frame_time().
158  *
159  * Returns: the frame time for the frame, in the timescale
160  *  of g_get_monotonic_time()
161  */
162 gint64
gdk_frame_timings_get_frame_time(GdkFrameTimings * timings)163 gdk_frame_timings_get_frame_time (GdkFrameTimings *timings)
164 {
165   g_return_val_if_fail (timings != NULL, 0);
166 
167   return timings->frame_time;
168 }
169 
170 /**
171  * gdk_frame_timings_get_presentation_time:
172  * @timings: a #GdkFrameTimings
173  *
174  * Reurns the presentation time. This is the time at which the frame
175  * became visible to the user.
176  *
177  * Returns: the time the frame was displayed to the user, in the
178  *  timescale of g_get_monotonic_time(), or 0 if no presentation
179  *  time is available. See gdk_frame_timings_get_complete()
180  * Since: 3.8
181  */
182 gint64
gdk_frame_timings_get_presentation_time(GdkFrameTimings * timings)183 gdk_frame_timings_get_presentation_time (GdkFrameTimings *timings)
184 {
185   g_return_val_if_fail (timings != NULL, 0);
186 
187   return timings->presentation_time;
188 }
189 
190 /**
191  * gdk_frame_timings_get_predicted_presentation_time:
192  * @timings: a #GdkFrameTimings
193  *
194  * Gets the predicted time at which this frame will be displayed. Although
195  * no predicted time may be available, if one is available, it will
196  * be available while the frame is being generated, in contrast to
197  * gdk_frame_timings_get_presentation_time(), which is only available
198  * after the frame has been presented. In general, if you are simply
199  * animating, you should use gdk_frame_clock_get_frame_time() rather
200  * than this function, but this function is useful for applications
201  * that want exact control over latency. For example, a movie player
202  * may want this information for Audio/Video synchronization.
203  *
204  * Returns: The predicted time at which the frame will be presented,
205  *  in the timescale of g_get_monotonic_time(), or 0 if no predicted
206  *  presentation time is available.
207  * Since: 3.8
208  */
209 gint64
gdk_frame_timings_get_predicted_presentation_time(GdkFrameTimings * timings)210 gdk_frame_timings_get_predicted_presentation_time (GdkFrameTimings *timings)
211 {
212   g_return_val_if_fail (timings != NULL, 0);
213 
214   return timings->predicted_presentation_time;
215 }
216 
217 /**
218  * gdk_frame_timings_get_refresh_interval:
219  * @timings: a #GdkFrameTimings
220  *
221  * Gets the natural interval between presentation times for
222  * the display that this frame was displayed on. Frame presentation
223  * usually happens during the “vertical blanking interval”.
224  *
225  * Returns: the refresh interval of the display, in microseconds,
226  *  or 0 if the refresh interval is not available.
227  *  See gdk_frame_timings_get_complete().
228  * Since: 3.8
229  */
230 gint64
gdk_frame_timings_get_refresh_interval(GdkFrameTimings * timings)231 gdk_frame_timings_get_refresh_interval (GdkFrameTimings *timings)
232 {
233   g_return_val_if_fail (timings != NULL, 0);
234 
235   return timings->refresh_interval;
236 }
237