src/timer/windows/SDL_systimer.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 09 Apr 2015 22:28:37 -0400
changeset 9541 cf8fab52e33b
parent 9222 f4ef6e5fb804
child 9566 7454bfce9202
permissions -rw-r--r--
Merged Alex Szpakowski's iOS-improvement branch to default.

Fixes Bugzilla #2798.
Fixes Bugzilla #2212.
Fixes Bugzilla #2826.
Fixes Bugzilla #2661.
Fixes Bugzilla #1885.
Fixes Bugzilla #1578.
Fixes Bugzilla #2751.

(whew!)

Notable changes, from Alex's notes:

- The SDL_WINDOW_ALLOW_HIGHDPI flag is now needed (along with SDL_GL_GetDrawableSize or SDL_GetRendererOutputSize) to use Retina / high DPI resolutions, bringing SDL’s Retina-related behavior on iOS in line with Mac OS X. Window dimensions and display modes are now in the “points” (non-high DPI) coordinate system rather than pixels, whereas SDL_GL_GetDrawableSize is in pixels.

- Reworked the custom extended launch screen code:
- It now hides after the first SDL_PumpEvents call rather than SDL_CreateWindow, and it fades out in a similar manner to the system launch screen behavior.
- It now mirrors the system launch screen behavior when deciding which image to display: it falls back to using the Launch Images dictionary in Info.plist if the iOS 8+ launch screen nib isn’t available, and if the Launch Images dictionary doesn’t exist it uses the old standard launch image names.
- The extended launch screen can now be disabled via the SDL_IPHONE_LAUNCHSCREEN define in SDL_config_iphoneos.h.

- Added support for SDL_HINT_ACCELEROMETER_AS_JOYSTICK.

- Added access to a window view's renderbuffer and framebuffer to syswm.

- Added OpenGL ES debug labels for the Renderbuffer and Framebuffer Objects created with SDL_GL_CreateContext.

- Added support for sRGB OpenGL ES contexts on iOS 7+.

- Updated OpenGL ES contexts to support native-resolution rendering (when SDL_WINDOW_ALLOW_HIGHDPI is enabled) on the iPhone 6 Plus, i.e. 1080x1920 rather than 1242x2208.

- Updated SDL_GL_CreateContext, SDL_GL_SwapWindow, SDL_GL_MakeCurrent, and SDL_GL_DeleteContext to be more robust.

- Updated SDL windows to display a UIView at all times, even when an OpenGL context is not active. This allows rotation, touch events, and other windowing-related events to work properly without an active OpenGL context. It also makes it easier to use SDL_GetWindowWMInfo after creating a SDL window.

- Updated the iOS-specific Objective-C code to use cleaner and more modern language features and APIs, including ARC instead of manual reference counting.

- Updated SDL_HINT_ORIENTATIONS to allow disabling custom orientations if the hint is set with no valid orientation names.

- Fixed several rotation and orientation bugs with windows and display modes, especially in iOS 8+.

- Fixed SDL_SetWindowFullscreen failing to update the status bar visibility on iOS 7+.

- Fixed the orientation of the offset applied to the window’s view when the onscreen keyboard is shown in iOS 8+.

- Fixed SDL_IsScreenKeyboardShown (patch by Phil Hassey.)

- Fixed several major memory leaks caused by missing autorelease pool blocks in the iOS-specific Objective-C code.

- Removed several dead code paths.

- The iOS 7 SDK (Xcode 5) or newer is now required to build SDL for iOS.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@0
    22
slouken@5062
    23
#ifdef SDL_TIMER_WINDOWS
slouken@1635
    24
slouken@5090
    25
#include "../../core/windows/SDL_windows.h"
slouken@5114
    26
#include <mmsystem.h>
slouken@0
    27
slouken@0
    28
#include "SDL_timer.h"
slouken@7432
    29
#include "SDL_hints.h"
slouken@0
    30
slouken@0
    31
slouken@89
    32
/* The first (low-resolution) ticks value of the application */
slouken@0
    33
static DWORD start;
slouken@7650
    34
static BOOL ticks_started = FALSE; 
slouken@0
    35
slouken@89
    36
#ifndef USE_GETTICKCOUNT
slouken@89
    37
/* Store if a high-resolution performance counter exists on the system */
slouken@89
    38
static BOOL hires_timer_available;
slouken@89
    39
/* The first high-resolution ticks value of the application */
slouken@89
    40
static LARGE_INTEGER hires_start_ticks;
slouken@89
    41
/* The number of ticks per second of the high-resolution performance counter */
slouken@89
    42
static LARGE_INTEGER hires_ticks_per_second;
slouken@89
    43
dludwig@8478
    44
#ifndef __WINRT__
slouken@7432
    45
static void
slouken@7432
    46
timeSetPeriod(UINT uPeriod)
slouken@7432
    47
{
slouken@7432
    48
    static UINT timer_period = 0;
slouken@7432
    49
slouken@7432
    50
    if (uPeriod != timer_period) {
slouken@7432
    51
        if (timer_period) {
slouken@7432
    52
            timeEndPeriod(timer_period);
slouken@7432
    53
        }
slouken@7432
    54
slouken@7432
    55
        timer_period = uPeriod;
slouken@7432
    56
slouken@7432
    57
        if (timer_period) {
slouken@7432
    58
            timeBeginPeriod(timer_period);
slouken@7432
    59
        }
slouken@7432
    60
    }
slouken@7432
    61
}
slouken@7432
    62
slouken@7432
    63
static void
slouken@7432
    64
SDL_TimerResolutionChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
slouken@7432
    65
{
slouken@7432
    66
    UINT uPeriod;
slouken@7432
    67
slouken@7432
    68
    /* Unless the hint says otherwise, let's have good sleep precision */
slouken@7432
    69
    if (hint && *hint) {
slouken@7432
    70
        uPeriod = SDL_atoi(hint);
slouken@7432
    71
    } else {
slouken@7432
    72
        uPeriod = 1;
slouken@7432
    73
    }
slouken@7432
    74
    if (uPeriod || oldValue != hint) {
slouken@7432
    75
        timeSetPeriod(uPeriod);
slouken@7432
    76
    }
slouken@7432
    77
}
dludwig@8478
    78
#endif /* ifndef __WINRT__ */
slouken@7432
    79
slouken@8268
    80
#endif /* !USE_GETTICKCOUNT */
slouken@8268
    81
slouken@1895
    82
void
slouken@8268
    83
SDL_TicksInit(void)
slouken@0
    84
{
urkle@7649
    85
    if (ticks_started) {
urkle@7649
    86
        return;
urkle@7649
    87
    }
slouken@8268
    88
    ticks_started = SDL_TRUE;
urkle@7649
    89
slouken@1895
    90
    /* Set first ticks value */
slouken@0
    91
#ifdef USE_GETTICKCOUNT
slouken@1895
    92
    start = GetTickCount();
slouken@0
    93
#else
slouken@7191
    94
    /* QueryPerformanceCounter has had problems in the past, but lots of games
slouken@7136
    95
       use it, so we'll rely on it here.
slouken@7136
    96
     */
slouken@1895
    97
    if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE) {
slouken@1895
    98
        hires_timer_available = TRUE;
slouken@1895
    99
        QueryPerformanceCounter(&hires_start_ticks);
slouken@7136
   100
    } else {
slouken@1895
   101
        hires_timer_available = FALSE;
dludwig@8478
   102
#ifdef __WINRT__
dludwig@8478
   103
        start = 0;            /* the timer failed to start! */
dludwig@8478
   104
#else
slouken@7432
   105
        timeSetPeriod(1);     /* use 1 ms timer precision */
slouken@1895
   106
        start = timeGetTime();
slouken@8268
   107
slouken@8268
   108
        SDL_AddHintCallback(SDL_HINT_TIMER_RESOLUTION,
slouken@8268
   109
                            SDL_TimerResolutionChanged, NULL);
slouken@8583
   110
#endif /* __WINRT__ */
slouken@1895
   111
    }
slouken@8583
   112
#endif /* USE_GETTICKCOUNT */
slouken@8268
   113
}
slouken@7432
   114
slouken@8268
   115
void
slouken@8268
   116
SDL_TicksQuit(void)
slouken@8268
   117
{
slouken@8268
   118
#ifndef USE_GETTICKCOUNT
slouken@8268
   119
    if (!hires_timer_available) {
dludwig@8478
   120
#ifndef __WINRT__
slouken@8268
   121
        SDL_DelHintCallback(SDL_HINT_TIMER_RESOLUTION,
slouken@8268
   122
                            SDL_TimerResolutionChanged, NULL);
slouken@8268
   123
slouken@8268
   124
        timeSetPeriod(0);
slouken@8583
   125
#endif /* __WINRT__ */
icculus@7652
   126
    }
slouken@8583
   127
#endif /* USE_GETTICKCOUNT */
icculus@7652
   128
slouken@8268
   129
    ticks_started = SDL_FALSE;
slouken@0
   130
}
slouken@0
   131
slouken@1895
   132
Uint32
slouken@1895
   133
SDL_GetTicks(void)
slouken@0
   134
{
slouken@7432
   135
    DWORD now;
slouken@89
   136
#ifndef USE_GETTICKCOUNT
slouken@1895
   137
    LARGE_INTEGER hires_now;
slouken@89
   138
#endif
slouken@0
   139
icculus@7652
   140
    if (!ticks_started) {
slouken@8268
   141
        SDL_TicksInit();
icculus@7652
   142
    }
icculus@7652
   143
slouken@0
   144
#ifdef USE_GETTICKCOUNT
slouken@1895
   145
    now = GetTickCount();
slouken@0
   146
#else
slouken@1895
   147
    if (hires_timer_available) {
slouken@1895
   148
        QueryPerformanceCounter(&hires_now);
slouken@89
   149
slouken@1895
   150
        hires_now.QuadPart -= hires_start_ticks.QuadPart;
slouken@1895
   151
        hires_now.QuadPart *= 1000;
slouken@1895
   152
        hires_now.QuadPart /= hires_ticks_per_second.QuadPart;
slouken@89
   153
slouken@1895
   154
        return (DWORD) hires_now.QuadPart;
slouken@1895
   155
    } else {
dludwig@8478
   156
#ifdef __WINRT__
dludwig@8478
   157
        now = 0;
dludwig@8478
   158
#else
slouken@1895
   159
        now = timeGetTime();
slouken@8583
   160
#endif /* __WINRT__ */
slouken@1895
   161
    }
slouken@0
   162
#endif
slouken@89
   163
slouken@7432
   164
    return (now - start);
slouken@0
   165
}
slouken@0
   166
slouken@5514
   167
Uint64
slouken@5514
   168
SDL_GetPerformanceCounter(void)
slouken@5514
   169
{
slouken@5514
   170
    LARGE_INTEGER counter;
slouken@5514
   171
slouken@5514
   172
    if (!QueryPerformanceCounter(&counter)) {
slouken@5514
   173
        return SDL_GetTicks();
slouken@5514
   174
    }
slouken@5514
   175
    return counter.QuadPart;
slouken@5514
   176
}
slouken@5514
   177
slouken@5514
   178
Uint64
slouken@5514
   179
SDL_GetPerformanceFrequency(void)
slouken@5514
   180
{
slouken@5514
   181
    LARGE_INTEGER frequency;
slouken@5514
   182
slouken@5514
   183
    if (!QueryPerformanceFrequency(&frequency)) {
slouken@5514
   184
        return 1000;
slouken@5514
   185
    }
slouken@5514
   186
    return frequency.QuadPart;
slouken@5514
   187
}
slouken@5514
   188
dludwig@9222
   189
/* Sleep() is not publicly available to apps in early versions of WinRT.
dludwig@9222
   190
 *
dludwig@9222
   191
 * Visual C++ 2013 Update 4 re-introduced Sleep() for Windows 8.1 and
dludwig@9222
   192
 * Windows Phone 8.1.
dludwig@9222
   193
 *
dludwig@9222
   194
 * Use the compiler version to determine availability.
dludwig@9222
   195
 *
dludwig@9222
   196
 * NOTE #1: _MSC_FULL_VER == 180030723 for Visual C++ 2013 Update 3.
dludwig@9222
   197
 * NOTE #2: Visual C++ 2013, when compiling for Windows 8.0 and
dludwig@9222
   198
 *    Windows Phone 8.0, uses the Visual C++ 2012 compiler to build
dludwig@9222
   199
 *    apps and libraries.
dludwig@9222
   200
 */
dludwig@9222
   201
#if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723)
slouken@8582
   202
static void
slouken@8582
   203
Sleep(DWORD timeout)
slouken@8582
   204
{
slouken@8582
   205
    static HANDLE mutex = 0;
slouken@8582
   206
    if ( ! mutex )
slouken@8582
   207
    {
slouken@8582
   208
        mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS);
slouken@8582
   209
    }
slouken@8582
   210
    WaitForSingleObjectEx(mutex, timeout, FALSE);
slouken@8582
   211
}
dludwig@8478
   212
#endif
dludwig@8478
   213
slouken@1895
   214
void
slouken@1895
   215
SDL_Delay(Uint32 ms)
slouken@0
   216
{
slouken@1895
   217
    Sleep(ms);
slouken@0
   218
}
slouken@0
   219
slouken@5062
   220
#endif /* SDL_TIMER_WINDOWS */
slouken@5062
   221
slouken@1895
   222
/* vi: set ts=4 sw=4 expandtab: */