135 lines
4.0 KiB
C
135 lines
4.0 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)
|
|
{
|
|
g_get_current_time (&interval->start_time);
|
|
interval->fps = fps;
|
|
interval->frame_count = 0;
|
|
}
|
|
|
|
static guint
|
|
_clutter_timeout_interval_get_ticks (const GTimeVal *current_time,
|
|
ClutterTimeoutInterval *interval)
|
|
{
|
|
return ((current_time->tv_sec - interval->start_time.tv_sec) * 1000
|
|
+ (current_time->tv_usec - interval->start_time.tv_usec) / 1000);
|
|
}
|
|
|
|
gboolean
|
|
_clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
|
ClutterTimeoutInterval *interval,
|
|
gint *delay)
|
|
{
|
|
guint 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 */
|
|
g_time_val_add (&interval->start_time, -(gint) frame_time * 1000);
|
|
|
|
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;
|
|
glong b_difference;
|
|
gint comparison;
|
|
|
|
b_difference = ((a->start_time.tv_sec - b->start_time.tv_sec) * 1000
|
|
+ (a->start_time.tv_usec - b->start_time.tv_usec) / 1000);
|
|
|
|
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);
|
|
}
|