/* * Clutter. * * An OpenGL based 'interactive canvas' library. * * Authored By Neil Roberts * * 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 . */ #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); }