#include "SDL_atomic.h"
#include "SDL_cpuinfo.h"
#include "SDL_thread.h"
+#include "xf86drm.h"
+#include <fcntl.h>
/* #define DEBUG_TIMERS */
+char* timer_type = "NORMAL_TIMER";
+
typedef struct _SDL_Timer
{
int timerID;
/* List of timers - this is only touched by the timer thread */
SDL_Timer *timers;
+
+ int drm_fd;
+ drmVBlank vblankInfo;
} SDL_TimerData;
static SDL_TimerData SDL_timer_data;
* 3. Wait until next dispatch time or new timer arrives
*/
for ( ; ; ) {
- /* Pending and freelist maintenance */
- SDL_AtomicLock(&data->lock);
- {
- /* Get any timers ready to be queued */
- pending = data->pending;
- data->pending = NULL;
-
- /* Make any unused timer structures available */
- if (freelist_head) {
- freelist_tail->next = data->freelist;
- data->freelist = freelist_head;
+ if(SDL_strcmp(timer_type, "VSYNC_TIMER") == 0) {
+ if(!data->active)
+ break;
+ if(0 == drmWaitVBlank(data->drm_fd, &(data->vblankInfo))) {
+ if(data->pending) {
+ current = data->pending;
+ current->callback(current->interval, current->param);
+ }
}
- }
- SDL_AtomicUnlock(&data->lock);
- /* Sort the pending timers into our list */
- while (pending) {
- current = pending;
- pending = pending->next;
- SDL_AddTimerInternal(data, current);
}
- freelist_head = NULL;
- freelist_tail = NULL;
+ else {
+ /* Pending and freelist maintenance */
+ SDL_AtomicLock(&data->lock);
+ {
+ /* Get any timers ready to be queued */
+ pending = data->pending;
+ data->pending = NULL;
+
+ /* Make any unused timer structures available */
+ if (freelist_head) {
+ freelist_tail->next = data->freelist;
+ data->freelist = freelist_head;
+ }
+ }
+ SDL_AtomicUnlock(&data->lock);
- /* Check to see if we're still running, after maintenance */
- if (!data->active) {
- break;
- }
+ /* Sort the pending timers into our list */
+ while (pending) {
+ current = pending;
+ pending = pending->next;
+ SDL_AddTimerInternal(data, current);
+ }
+ freelist_head = NULL;
+ freelist_tail = NULL;
- /* Initial delay if there are no timers */
- delay = SDL_MUTEX_MAXWAIT;
+ /* Check to see if we're still running, after maintenance */
+ if (!data->active) {
+ break;
+ }
- tick = SDL_GetTicks();
+ /* Initial delay if there are no timers */
+ delay = SDL_MUTEX_MAXWAIT;
- /* Process all the pending timers for this tick */
- while (data->timers) {
- current = data->timers;
+ tick = SDL_GetTicks();
- if ((Sint32)(tick-current->scheduled) < 0) {
- /* Scheduled for the future, wait a bit */
- delay = (current->scheduled - tick);
- break;
- }
+ /* Process all the pending timers for this tick */
+ while (data->timers) {
+ current = data->timers;
- /* We're going to do something with this timer */
- data->timers = current->next;
+ if ((Sint32)(tick-current->scheduled) < 0) {
+ /* Scheduled for the future, wait a bit */
+ delay = (current->scheduled - tick);
+ break;
+ }
- if (current->canceled) {
- interval = 0;
- } else {
- interval = current->callback(current->interval, current->param);
- }
+ /* We're going to do something with this timer */
+ data->timers = current->next;
- if (interval > 0) {
- /* Reschedule this timer */
- current->scheduled = tick + interval;
- SDL_AddTimerInternal(data, current);
- } else {
- if (!freelist_head) {
- freelist_head = current;
+ if (current->canceled) {
+ interval = 0;
+ } else {
+ interval = current->callback(current->interval, current->param);
}
- if (freelist_tail) {
- freelist_tail->next = current;
+
+ if (interval > 0) {
+ /* Reschedule this timer */
+ current->scheduled = tick + interval;
+ SDL_AddTimerInternal(data, current);
+ } else {
+ if (!freelist_head) {
+ freelist_head = current;
+ }
+ if (freelist_tail) {
+ freelist_tail->next = current;
+ }
+ freelist_tail = current;
+
+ current->canceled = SDL_TRUE;
}
- freelist_tail = current;
+ }
- current->canceled = SDL_TRUE;
+ /* Adjust the delay based on processing time */
+ now = SDL_GetTicks();
+ interval = (now - tick);
+ if (interval > delay) {
+ delay = 0;
+ } else {
+ delay -= interval;
}
- }
- /* Adjust the delay based on processing time */
- now = SDL_GetTicks();
- interval = (now - tick);
- if (interval > delay) {
- delay = 0;
- } else {
- delay -= interval;
+ /* Note that each time a timer is added, this will return
+ immediately, but we process the timers added all at once.
+ That's okay, it just means we run through the loop a few
+ extra times.
+ */
+ SDL_SemWaitTimeout(data->sem, delay);
}
-
- /* Note that each time a timer is added, this will return
- immediately, but we process the timers added all at once.
- That's okay, it just means we run through the loop a few
- extra times.
- */
- SDL_SemWaitTimeout(data->sem, delay);
}
return 0;
}
int
SDL_TimerInit(void)
{
+ timer_type = getenv("SDL_TIMER_TYPE");
+ if(NULL == timer_type)
+ {
+ timer_type = "NORMAL_TIMER";
+ }
SDL_TimerData *data = &SDL_timer_data;
if (!data->active) {
}
data->active = SDL_TRUE;
+
+ if(SDL_strcmp(timer_type, "VSYNC_TIMER") == 0) {
+ const char* DRM_DEVICE = "/dev/dri/card0";
+ data->drm_fd = open( DRM_DEVICE, O_RDWR );
+
+ data->vblankInfo.request.type = DRM_VBLANK_NEXTONMISS;
+ data->vblankInfo.request.sequence = 0;
+ data->vblankInfo.request.signal = 0;
+
+ data->vblankInfo.reply.type = DRM_VBLANK_NEXTONMISS;
+ data->vblankInfo.reply.sequence = 0;
+ data->vblankInfo.reply.tval_sec = 0;
+ data->vblankInfo.reply.tval_usec = 0;
+ }
/* !!! FIXME: this is nasty. */
#if defined(__WIN32__) && !defined(HAVE_LIBC)
#undef SDL_CreateThread