cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_systimer.c (5520B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../../SDL_internal.h"
     22
     23#ifdef SDL_TIMER_UNIX
     24
     25#include <stdio.h>
     26#include <sys/time.h>
     27#include <unistd.h>
     28#include <errno.h>
     29
     30#include "SDL_timer.h"
     31#include "SDL_assert.h"
     32
     33/* The clock_gettime provides monotonous time, so we should use it if
     34   it's available. The clock_gettime function is behind ifdef
     35   for __USE_POSIX199309
     36   Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005
     37*/
     38/* Reworked monotonic clock to not assume the current system has one
     39   as not all linux kernels provide a monotonic clock (yeah recent ones
     40   probably do)
     41   Also added OS X Monotonic clock support
     42   Based on work in https://github.com/ThomasHabets/monotonic_clock
     43 */
     44#if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME
     45#include <time.h>
     46#endif
     47#ifdef __APPLE__
     48#include <mach/mach_time.h>
     49#endif
     50
     51/* The first ticks value of the application */
     52#if HAVE_CLOCK_GETTIME
     53static struct timespec start_ts;
     54#elif defined(__APPLE__)
     55static uint64_t start_mach;
     56mach_timebase_info_data_t mach_base_info;
     57#endif
     58static SDL_bool has_monotonic_time = SDL_FALSE;
     59static struct timeval start_tv;
     60static SDL_bool ticks_started = SDL_FALSE;
     61
     62void
     63SDL_TicksInit(void)
     64{
     65    if (ticks_started) {
     66        return;
     67    }
     68    ticks_started = SDL_TRUE;
     69
     70    /* Set first ticks value */
     71#if HAVE_CLOCK_GETTIME
     72    if (clock_gettime(CLOCK_MONOTONIC, &start_ts) == 0) {
     73        has_monotonic_time = SDL_TRUE;
     74    } else
     75#elif defined(__APPLE__)
     76    kern_return_t ret = mach_timebase_info(&mach_base_info);
     77    if (ret == 0) {
     78        has_monotonic_time = SDL_TRUE;
     79        start_mach = mach_absolute_time();
     80    } else
     81#endif
     82    {
     83        gettimeofday(&start_tv, NULL);
     84    }
     85}
     86
     87void
     88SDL_TicksQuit(void)
     89{
     90    ticks_started = SDL_FALSE;
     91}
     92
     93Uint32
     94SDL_GetTicks(void)
     95{
     96    Uint32 ticks;
     97    if (!ticks_started) {
     98        SDL_TicksInit();
     99    }
    100
    101    if (has_monotonic_time) {
    102#if HAVE_CLOCK_GETTIME
    103        struct timespec now;
    104        clock_gettime(CLOCK_MONOTONIC, &now);
    105        ticks = (now.tv_sec - start_ts.tv_sec) * 1000 + (now.tv_nsec -
    106                                                 start_ts.tv_nsec) / 1000000;
    107#elif defined(__APPLE__)
    108        uint64_t now = mach_absolute_time();
    109        ticks = (Uint32)((((now - start_mach) * mach_base_info.numer) / mach_base_info.denom) / 1000000);
    110#else
    111        SDL_assert(SDL_FALSE);
    112        ticks = 0;
    113#endif
    114    } else {
    115        struct timeval now;
    116
    117        gettimeofday(&now, NULL);
    118        ticks = (Uint32)((now.tv_sec - start_tv.tv_sec) * 1000 + (now.tv_usec - start_tv.tv_usec) / 1000);
    119    }
    120    return (ticks);
    121}
    122
    123Uint64
    124SDL_GetPerformanceCounter(void)
    125{
    126    Uint64 ticks;
    127    if (!ticks_started) {
    128        SDL_TicksInit();
    129    }
    130
    131    if (has_monotonic_time) {
    132#if HAVE_CLOCK_GETTIME
    133        struct timespec now;
    134
    135        clock_gettime(CLOCK_MONOTONIC, &now);
    136        ticks = now.tv_sec;
    137        ticks *= 1000000000;
    138        ticks += now.tv_nsec;
    139#elif defined(__APPLE__)
    140        ticks = mach_absolute_time();
    141#else
    142        SDL_assert(SDL_FALSE);
    143        ticks = 0;
    144#endif
    145    } else {
    146        struct timeval now;
    147
    148        gettimeofday(&now, NULL);
    149        ticks = now.tv_sec;
    150        ticks *= 1000000;
    151        ticks += now.tv_usec;
    152    }
    153    return (ticks);
    154}
    155
    156Uint64
    157SDL_GetPerformanceFrequency(void)
    158{
    159    if (!ticks_started) {
    160        SDL_TicksInit();
    161    }
    162
    163    if (has_monotonic_time) {
    164#if HAVE_CLOCK_GETTIME
    165        return 1000000000;
    166#elif defined(__APPLE__)
    167        Uint64 freq = mach_base_info.denom;
    168        freq *= 1000000000;
    169        freq /= mach_base_info.numer;
    170        return freq;
    171#endif
    172    } 
    173        
    174    return 1000000;
    175}
    176
    177void
    178SDL_Delay(Uint32 ms)
    179{
    180    int was_error;
    181
    182#if HAVE_NANOSLEEP
    183    struct timespec elapsed, tv;
    184#else
    185    struct timeval tv;
    186    Uint32 then, now, elapsed;
    187#endif
    188
    189    /* Set the timeout interval */
    190#if HAVE_NANOSLEEP
    191    elapsed.tv_sec = ms / 1000;
    192    elapsed.tv_nsec = (ms % 1000) * 1000000;
    193#else
    194    then = SDL_GetTicks();
    195#endif
    196    do {
    197        errno = 0;
    198
    199#if HAVE_NANOSLEEP
    200        tv.tv_sec = elapsed.tv_sec;
    201        tv.tv_nsec = elapsed.tv_nsec;
    202        was_error = nanosleep(&tv, &elapsed);
    203#else
    204        /* Calculate the time interval left (in case of interrupt) */
    205        now = SDL_GetTicks();
    206        elapsed = (now - then);
    207        then = now;
    208        if (elapsed >= ms) {
    209            break;
    210        }
    211        ms -= elapsed;
    212        tv.tv_sec = ms / 1000;
    213        tv.tv_usec = (ms % 1000) * 1000;
    214
    215        was_error = select(0, NULL, NULL, NULL, &tv);
    216#endif /* HAVE_NANOSLEEP */
    217    } while (was_error && (errno == EINTR));
    218}
    219
    220#endif /* SDL_TIMER_UNIX */
    221
    222/* vi: set ts=4 sw=4 expandtab: */