1
0
Fork 0
mutter-performance-source/clutter/clutter-timeout-interval.c
Emmanuele Bassi 8f60d5a3a2 Start using the monotonic API in GLib ≥ 2.27
Starting from the 2.27 cycle, GLib is exposing a monotonic clock with
microseconds granularity throughout the time-based API. We can start
using it, given that the old, non-monotonic version is going to be
deprecated by the same cycle.
2010-11-17 16:19:10 +00:00

140 lines
3.9 KiB
C

/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Neil Roberts <neil@linux.intel.com>
*
* Copyright (C) 2009 Intel Corporation.
*
* 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/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* This file contains the common code to check whether an interval has
expired used in clutter-frame-source and clutter-timeout-pool. */
#include "clutter-timeout-interval.h"
void
_clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
guint fps)
{
#if GLIB_CHECK_VERSION (2, 27, 3)
interval->start_time = g_get_monotonic_time () / 1000;
#else
{
GTimeVal start_time;
g_get_current_time (&start_time);
interval->start_time = start_time.tv_sec * 1000
+ start_time.tv_usec / 1000;
}
#endif
interval->fps = fps;
interval->frame_count = 0;
}
static gint64
_clutter_timeout_interval_get_ticks (gint64 current_time,
ClutterTimeoutInterval *interval)
{
return MAX (current_time - interval->start_time, 0);
}
gboolean
_clutter_timeout_interval_prepare (gint64 current_time,
ClutterTimeoutInterval *interval,
gint *delay)
{
gint elapsed_time, new_frame_num;
elapsed_time = _clutter_timeout_interval_get_ticks (current_time, interval);
new_frame_num = elapsed_time * interval->fps / 1000;
/* If time has gone backwards or the time since the last frame is
greater than the two frames worth then reset the time and do a
frame now */
if (new_frame_num < interval->frame_count ||
new_frame_num - interval->frame_count > 2)
{
/* Get the frame time rounded up to the nearest ms */
guint frame_time = (1000 + interval->fps - 1) / interval->fps;
/* Reset the start time */
interval->start_time = current_time;
/* Move the start time as if one whole frame has elapsed */
interval->start_time -= frame_time;
interval->frame_count = 0;
if (delay)
*delay = 0;
return TRUE;
}
else if (new_frame_num > interval->frame_count)
{
if (delay)
*delay = 0;
return TRUE;
}
else
{
if (delay)
*delay = ((interval->frame_count + 1) * 1000 / interval->fps
- elapsed_time);
return FALSE;
}
}
gboolean
_clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
GSourceFunc callback,
gpointer user_data)
{
if ((* callback) (user_data))
{
interval->frame_count++;
return TRUE;
}
return FALSE;
}
gint
_clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a,
const ClutterTimeoutInterval *b)
{
guint a_delay = 1000 / a->fps;
guint b_delay = 1000 / b->fps;
gint64 b_difference;
gint comparison;
b_difference = a->start_time - b->start_time;
comparison = ((gint) ((a->frame_count + 1) * a_delay)
- (gint) ((b->frame_count + 1) * b_delay + b_difference));
return (comparison < 0 ? -1
: comparison > 0 ? 1
: 0);
}