Convert ticks to 64-bit, added nanosecond precision to the API

Fixes https://github.com/libsdl-org/SDL/issues/5512
Fixes https://github.com/libsdl-org/SDL/issues/6731
main
Sam Lantinga 2022-12-02 01:17:17 -08:00
parent 764b899a13
commit 8121bbd083
96 changed files with 938 additions and 1243 deletions

View File

@ -32,4 +32,10 @@ General:
* Added SDL_CreateSurface() and SDL_CreateSurfaceFrom() which replace the SDL_CreateRGBSurface*() * Added SDL_CreateSurface() and SDL_CreateSurfaceFrom() which replace the SDL_CreateRGBSurface*()
* Removed unused 'flags' parameter from SDL_ConvertSurface and SDL_ConvertSurfaceFormat * Removed unused 'flags' parameter from SDL_ConvertSurface and SDL_ConvertSurfaceFormat
* Removed 'SDL_GL_CONTEXT_EGL' from OpenGL configuration attributes * Removed 'SDL_GL_CONTEXT_EGL' from OpenGL configuration attributes
* SDL_GetTicks() now returns a 64-bit value and the tick values should be directly compared instead of using the SDL_TICKS_PASSED macro
* Added SDL_GetTicksNS() to return the number of nanoseconds since the SDL library initialized
* Added SDL_DelayNS() to specify a delay in nanoseconds, to the highest precision the system will support
* Added SDL_WaitEventTimeoutNS() to wait for events with the highest possible precision
* Added SDL_SemWaitTimeoutNS() to wait for a semaphore with the highest possible precision
* Added SDL_CondWaitTimeoutNS() to wait for a condition variable the highest possible precision
* The timestamp member of the SDL_Event structure is now in nanoseconds, filled in with SDL_GetTicksNS()

View File

@ -31,6 +31,10 @@ LDFLAGS += $(shell pkg-config sdl3 --libs)
The SDL3main and SDL3test libraries have been renamed SDL3_main and SDL3_test, respectively. The SDL3main and SDL3test libraries have been renamed SDL3_main and SDL3_test, respectively.
## SDL_events.h
The `timestamp` member of the SDL_Event structure now represents nanoseconds, and is populated with `SDL_GetTicksNS()`
## SDL_platform.h ## SDL_platform.h
The preprocessor symbol __MACOSX__ has been renamed __MACOS__, and __IPHONEOS__ has been renamed __IOS__ The preprocessor symbol __MACOSX__ has been renamed __MACOS__, and __IPHONEOS__ has been renamed __IOS__
@ -223,6 +227,30 @@ The structures in this file are versioned separately from the rest of SDL, allow
This function now returns a standard int result instead of SDL_bool, returning 0 if the function succeeds or a negative error code if there was an error. You should also pass `SDL_SYSWM_CURRENT_VERSION` as the new third version parameter. The version member of the info structure will be filled in with the version of data that is returned, the minimum of the version you requested and the version supported by the runtime SDL library. This function now returns a standard int result instead of SDL_bool, returning 0 if the function succeeds or a negative error code if there was an error. You should also pass `SDL_SYSWM_CURRENT_VERSION` as the new third version parameter. The version member of the info structure will be filled in with the version of data that is returned, the minimum of the version you requested and the version supported by the runtime SDL library.
## SDL_timer.h
SDL_GetTicks() now returns a 64-bit value. Instead of using the `SDL_TICKS_PASSED` macro, you can directly compare tick values, e.g.
```c
Uint32 deadline = SDL_GetTicks() + 1000;
...
if (SDL_TICKS_PASSED(SDL_GetTicks(), deadline)) {
...
}
```
becomes:
```c
Uint64 deadline = SDL_GetTicks() + 1000
...
if (SDL_GetTicks() >= deadline) {
...
}
```
If you were using this macro for other things besides SDL ticks values, you can define it in your own code as:
```c
#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0)
```
## SDL_version.h ## SDL_version.h
SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0 SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0

View File

@ -182,7 +182,7 @@ typedef enum
typedef struct SDL_CommonEvent typedef struct SDL_CommonEvent
{ {
Uint32 type; Uint32 type;
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
} SDL_CommonEvent; } SDL_CommonEvent;
/** /**
@ -191,7 +191,7 @@ typedef struct SDL_CommonEvent
typedef struct SDL_DisplayEvent typedef struct SDL_DisplayEvent
{ {
Uint32 type; /**< ::SDL_DISPLAYEVENT */ Uint32 type; /**< ::SDL_DISPLAYEVENT */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 display; /**< The associated display index */ Uint32 display; /**< The associated display index */
Uint8 event; /**< ::SDL_DisplayEventID */ Uint8 event; /**< ::SDL_DisplayEventID */
Uint8 padding1; Uint8 padding1;
@ -206,7 +206,7 @@ typedef struct SDL_DisplayEvent
typedef struct SDL_WindowEvent typedef struct SDL_WindowEvent
{ {
Uint32 type; /**< ::SDL_WINDOWEVENT */ Uint32 type; /**< ::SDL_WINDOWEVENT */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The associated window */ Uint32 windowID; /**< The associated window */
Uint8 event; /**< ::SDL_WindowEventID */ Uint8 event; /**< ::SDL_WindowEventID */
Uint8 padding1; Uint8 padding1;
@ -222,7 +222,7 @@ typedef struct SDL_WindowEvent
typedef struct SDL_KeyboardEvent typedef struct SDL_KeyboardEvent
{ {
Uint32 type; /**< ::SDL_KEYDOWN or ::SDL_KEYUP */ Uint32 type; /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The window with keyboard focus, if any */ Uint32 windowID; /**< The window with keyboard focus, if any */
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
Uint8 repeat; /**< Non-zero if this is a key repeat */ Uint8 repeat; /**< Non-zero if this is a key repeat */
@ -238,7 +238,7 @@ typedef struct SDL_KeyboardEvent
typedef struct SDL_TextEditingEvent typedef struct SDL_TextEditingEvent
{ {
Uint32 type; /**< ::SDL_TEXTEDITING */ Uint32 type; /**< ::SDL_TEXTEDITING */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The window with keyboard focus, if any */ Uint32 windowID; /**< The window with keyboard focus, if any */
char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */ char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */
Sint32 start; /**< The start cursor of selected editing text */ Sint32 start; /**< The start cursor of selected editing text */
@ -252,7 +252,7 @@ typedef struct SDL_TextEditingEvent
typedef struct SDL_TextEditingExtEvent typedef struct SDL_TextEditingExtEvent
{ {
Uint32 type; /**< ::SDL_TEXTEDITING_EXT */ Uint32 type; /**< ::SDL_TEXTEDITING_EXT */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The window with keyboard focus, if any */ Uint32 windowID; /**< The window with keyboard focus, if any */
char* text; /**< The editing text, which should be freed with SDL_free(), and will not be NULL */ char* text; /**< The editing text, which should be freed with SDL_free(), and will not be NULL */
Sint32 start; /**< The start cursor of selected editing text */ Sint32 start; /**< The start cursor of selected editing text */
@ -266,7 +266,7 @@ typedef struct SDL_TextEditingExtEvent
typedef struct SDL_TextInputEvent typedef struct SDL_TextInputEvent
{ {
Uint32 type; /**< ::SDL_TEXTINPUT */ Uint32 type; /**< ::SDL_TEXTINPUT */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The window with keyboard focus, if any */ Uint32 windowID; /**< The window with keyboard focus, if any */
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */
} SDL_TextInputEvent; } SDL_TextInputEvent;
@ -277,7 +277,7 @@ typedef struct SDL_TextInputEvent
typedef struct SDL_MouseMotionEvent typedef struct SDL_MouseMotionEvent
{ {
Uint32 type; /**< ::SDL_MOUSEMOTION */ Uint32 type; /**< ::SDL_MOUSEMOTION */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The window with mouse focus, if any */ Uint32 windowID; /**< The window with mouse focus, if any */
Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
Uint32 state; /**< The current button state */ Uint32 state; /**< The current button state */
@ -293,7 +293,7 @@ typedef struct SDL_MouseMotionEvent
typedef struct SDL_MouseButtonEvent typedef struct SDL_MouseButtonEvent
{ {
Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */ Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The window with mouse focus, if any */ Uint32 windowID; /**< The window with mouse focus, if any */
SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
Uint8 button; /**< The mouse button index */ Uint8 button; /**< The mouse button index */
@ -310,7 +310,7 @@ typedef struct SDL_MouseButtonEvent
typedef struct SDL_MouseWheelEvent typedef struct SDL_MouseWheelEvent
{ {
Uint32 type; /**< ::SDL_MOUSEWHEEL */ Uint32 type; /**< ::SDL_MOUSEWHEEL */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The window with mouse focus, if any */ Uint32 windowID; /**< The window with mouse focus, if any */
SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */ Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
@ -328,7 +328,7 @@ typedef struct SDL_MouseWheelEvent
typedef struct SDL_JoyAxisEvent typedef struct SDL_JoyAxisEvent
{ {
Uint32 type; /**< ::SDL_JOYAXISMOTION */ Uint32 type; /**< ::SDL_JOYAXISMOTION */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Uint8 axis; /**< The joystick axis index */ Uint8 axis; /**< The joystick axis index */
Uint8 padding1; Uint8 padding1;
@ -344,7 +344,7 @@ typedef struct SDL_JoyAxisEvent
typedef struct SDL_JoyBallEvent typedef struct SDL_JoyBallEvent
{ {
Uint32 type; /**< ::SDL_JOYBALLMOTION */ Uint32 type; /**< ::SDL_JOYBALLMOTION */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Uint8 ball; /**< The joystick trackball index */ Uint8 ball; /**< The joystick trackball index */
Uint8 padding1; Uint8 padding1;
@ -360,7 +360,7 @@ typedef struct SDL_JoyBallEvent
typedef struct SDL_JoyHatEvent typedef struct SDL_JoyHatEvent
{ {
Uint32 type; /**< ::SDL_JOYHATMOTION */ Uint32 type; /**< ::SDL_JOYHATMOTION */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Uint8 hat; /**< The joystick hat index */ Uint8 hat; /**< The joystick hat index */
Uint8 value; /**< The hat position value. Uint8 value; /**< The hat position value.
@ -380,7 +380,7 @@ typedef struct SDL_JoyHatEvent
typedef struct SDL_JoyButtonEvent typedef struct SDL_JoyButtonEvent
{ {
Uint32 type; /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */ Uint32 type; /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Uint8 button; /**< The joystick button index */ Uint8 button; /**< The joystick button index */
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
@ -394,7 +394,7 @@ typedef struct SDL_JoyButtonEvent
typedef struct SDL_JoyDeviceEvent typedef struct SDL_JoyDeviceEvent
{ {
Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */ Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */ SDL_JoystickID which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */
} SDL_JoyDeviceEvent; } SDL_JoyDeviceEvent;
@ -404,7 +404,7 @@ typedef struct SDL_JoyDeviceEvent
typedef struct SDL_JoyBatteryEvent typedef struct SDL_JoyBatteryEvent
{ {
Uint32 type; /**< ::SDL_JOYBATTERYUPDATED */ Uint32 type; /**< ::SDL_JOYBATTERYUPDATED */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
SDL_JoystickPowerLevel level; /**< The joystick battery level */ SDL_JoystickPowerLevel level; /**< The joystick battery level */
} SDL_JoyBatteryEvent; } SDL_JoyBatteryEvent;
@ -415,7 +415,7 @@ typedef struct SDL_JoyBatteryEvent
typedef struct SDL_ControllerAxisEvent typedef struct SDL_ControllerAxisEvent
{ {
Uint32 type; /**< ::SDL_CONTROLLERAXISMOTION */ Uint32 type; /**< ::SDL_CONTROLLERAXISMOTION */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Uint8 axis; /**< The controller axis (SDL_GameControllerAxis) */ Uint8 axis; /**< The controller axis (SDL_GameControllerAxis) */
Uint8 padding1; Uint8 padding1;
@ -432,7 +432,7 @@ typedef struct SDL_ControllerAxisEvent
typedef struct SDL_ControllerButtonEvent typedef struct SDL_ControllerButtonEvent
{ {
Uint32 type; /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */ Uint32 type; /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Uint8 button; /**< The controller button (SDL_GameControllerButton) */ Uint8 button; /**< The controller button (SDL_GameControllerButton) */
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
@ -447,7 +447,7 @@ typedef struct SDL_ControllerButtonEvent
typedef struct SDL_ControllerDeviceEvent typedef struct SDL_ControllerDeviceEvent
{ {
Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */ Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ SDL_JoystickID which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
} SDL_ControllerDeviceEvent; } SDL_ControllerDeviceEvent;
@ -457,7 +457,7 @@ typedef struct SDL_ControllerDeviceEvent
typedef struct SDL_ControllerTouchpadEvent typedef struct SDL_ControllerTouchpadEvent
{ {
Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */ Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Sint32 touchpad; /**< The index of the touchpad */ Sint32 touchpad; /**< The index of the touchpad */
Sint32 finger; /**< The index of the finger on the touchpad */ Sint32 finger; /**< The index of the finger on the touchpad */
@ -472,7 +472,7 @@ typedef struct SDL_ControllerTouchpadEvent
typedef struct SDL_ControllerSensorEvent typedef struct SDL_ControllerSensorEvent
{ {
Uint32 type; /**< ::SDL_CONTROLLERSENSORUPDATE */ Uint32 type; /**< ::SDL_CONTROLLERSENSORUPDATE */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickID which; /**< The joystick instance id */
Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */ Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */
float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */ float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */
@ -485,7 +485,7 @@ typedef struct SDL_ControllerSensorEvent
typedef struct SDL_AudioDeviceEvent typedef struct SDL_AudioDeviceEvent
{ {
Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */ Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */ Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */ Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */
Uint8 padding1; Uint8 padding1;
@ -500,7 +500,7 @@ typedef struct SDL_AudioDeviceEvent
typedef struct SDL_TouchFingerEvent typedef struct SDL_TouchFingerEvent
{ {
Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */ Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_TouchID touchId; /**< The touch device id */ SDL_TouchID touchId; /**< The touch device id */
SDL_FingerID fingerId; SDL_FingerID fingerId;
float x; /**< Normalized in the range 0...1 */ float x; /**< Normalized in the range 0...1 */
@ -518,7 +518,7 @@ typedef struct SDL_TouchFingerEvent
typedef struct SDL_MultiGestureEvent typedef struct SDL_MultiGestureEvent
{ {
Uint32 type; /**< ::SDL_MULTIGESTURE */ Uint32 type; /**< ::SDL_MULTIGESTURE */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_TouchID touchId; /**< The touch device id */ SDL_TouchID touchId; /**< The touch device id */
float dTheta; float dTheta;
float dDist; float dDist;
@ -535,7 +535,7 @@ typedef struct SDL_MultiGestureEvent
typedef struct SDL_DollarGestureEvent typedef struct SDL_DollarGestureEvent
{ {
Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */ Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_TouchID touchId; /**< The touch device id */ SDL_TouchID touchId; /**< The touch device id */
SDL_GestureID gestureId; SDL_GestureID gestureId;
Uint32 numFingers; Uint32 numFingers;
@ -553,7 +553,7 @@ typedef struct SDL_DollarGestureEvent
typedef struct SDL_DropEvent typedef struct SDL_DropEvent
{ {
Uint32 type; /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */ Uint32 type; /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */ char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
Uint32 windowID; /**< The window that was dropped on, if any */ Uint32 windowID; /**< The window that was dropped on, if any */
} SDL_DropEvent; } SDL_DropEvent;
@ -565,7 +565,7 @@ typedef struct SDL_DropEvent
typedef struct SDL_SensorEvent typedef struct SDL_SensorEvent
{ {
Uint32 type; /**< ::SDL_SENSORUPDATE */ Uint32 type; /**< ::SDL_SENSORUPDATE */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_SensorID which; /**< The instance ID of the sensor */ SDL_SensorID which; /**< The instance ID of the sensor */
float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */ float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */ Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */
@ -577,7 +577,7 @@ typedef struct SDL_SensorEvent
typedef struct SDL_QuitEvent typedef struct SDL_QuitEvent
{ {
Uint32 type; /**< ::SDL_QUIT */ Uint32 type; /**< ::SDL_QUIT */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
} SDL_QuitEvent; } SDL_QuitEvent;
/** /**
@ -586,7 +586,7 @@ typedef struct SDL_QuitEvent
typedef struct SDL_OSEvent typedef struct SDL_OSEvent
{ {
Uint32 type; /**< ::SDL_QUIT */ Uint32 type; /**< ::SDL_QUIT */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
} SDL_OSEvent; } SDL_OSEvent;
/** /**
@ -595,7 +595,7 @@ typedef struct SDL_OSEvent
typedef struct SDL_UserEvent typedef struct SDL_UserEvent
{ {
Uint32 type; /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */ Uint32 type; /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint32 windowID; /**< The associated window if any */ Uint32 windowID; /**< The associated window if any */
Sint32 code; /**< User defined event code */ Sint32 code; /**< User defined event code */
void *data1; /**< User defined data pointer */ void *data1; /**< User defined data pointer */
@ -615,7 +615,7 @@ typedef struct SDL_SysWMmsg SDL_SysWMmsg;
typedef struct SDL_SysWMEvent typedef struct SDL_SysWMEvent
{ {
Uint32 type; /**< ::SDL_SYSWMEVENT */ Uint32 type; /**< ::SDL_SYSWMEVENT */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_SysWMmsg *msg; /**< driver dependent data, defined in SDL_syswm.h */ SDL_SysWMmsg *msg; /**< driver dependent data, defined in SDL_syswm.h */
} SDL_SysWMEvent; } SDL_SysWMEvent;
@ -669,7 +669,7 @@ typedef union SDL_Event
the next multiple of 16, 64, and on architectures where pointers are the next multiple of 16, 64, and on architectures where pointers are
even larger the size of SDL_UserEvent will dominate as being 3 pointers. even larger the size of SDL_UserEvent will dominate as being 3 pointers.
*/ */
Uint8 padding[sizeof(void *) <= 8 ? 56 : sizeof(void *) == 16 ? 64 : 3 * sizeof(void *)]; Uint8 padding[128];
} SDL_Event; } SDL_Event;
/* Make sure we haven't broken binary compatibility */ /* Make sure we haven't broken binary compatibility */
@ -879,6 +879,7 @@ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType);
* \sa SDL_SetEventFilter * \sa SDL_SetEventFilter
* \sa SDL_WaitEvent * \sa SDL_WaitEvent
* \sa SDL_WaitEventTimeout * \sa SDL_WaitEventTimeout
* \sa SDL_WaitEventTimeoutNS
*/ */
extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event); extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event);
@ -901,8 +902,9 @@ extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event);
* \sa SDL_PollEvent * \sa SDL_PollEvent
* \sa SDL_PumpEvents * \sa SDL_PumpEvents
* \sa SDL_WaitEventTimeout * \sa SDL_WaitEventTimeout
* \sa SDL_WaitEventTimeoutNS
*/ */
extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event); extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event *event);
/** /**
* Wait until the specified timeout (in milliseconds) for the next available * Wait until the specified timeout (in milliseconds) for the next available
@ -914,9 +916,12 @@ extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event);
* As this function may implicitly call SDL_PumpEvents(), you can only call * As this function may implicitly call SDL_PumpEvents(), you can only call
* this function in the thread that initialized the video subsystem. * this function in the thread that initialized the video subsystem.
* *
* The timeout is not guaranteed, the actual wait time could be longer
* due to system scheduling.
*
* \param event the SDL_Event structure to be filled in with the next event * \param event the SDL_Event structure to be filled in with the next event
* from the queue, or NULL * from the queue, or NULL
* \param timeout the maximum number of milliseconds to wait for the next * \param timeoutMS the maximum number of milliseconds to wait for the next
* available event * available event
* \returns 1 on success or 0 if there was an error while waiting for events; * \returns 1 on success or 0 if there was an error while waiting for events;
* call SDL_GetError() for more information. This also returns 0 if * call SDL_GetError() for more information. This also returns 0 if
@ -927,9 +932,39 @@ extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event);
* \sa SDL_PollEvent * \sa SDL_PollEvent
* \sa SDL_PumpEvents * \sa SDL_PumpEvents
* \sa SDL_WaitEvent * \sa SDL_WaitEvent
* \sa SDL_WaitEventTimeoutNS
*/ */
extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event * event, extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS);
int timeout);
/**
* Wait until the specified timeout (in nanoseconds) for the next available
* event.
*
* If `event` is not NULL, the next event is removed from the queue and stored
* in the SDL_Event structure pointed to by `event`.
*
* As this function may implicitly call SDL_PumpEvents(), you can only call
* this function in the thread that initialized the video subsystem.
*
* The timeout is not guaranteed, the actual wait time could be longer
* due to system scheduling.
*
* \param event the SDL_Event structure to be filled in with the next event
* from the queue, or NULL
* \param timeoutNS the maximum number of nanoseconds to wait for the next
* available event
* \returns 1 on success or 0 if there was an error while waiting for events;
* call SDL_GetError() for more information. This also returns 0 if
* the timeout elapsed without an event arriving.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_PollEvent
* \sa SDL_PumpEvents
* \sa SDL_WaitEvent
* \sa SDL_WaitEventTimeout
*/
extern DECLSPEC int SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS);
/** /**
* Add an event to the event queue. * Add an event to the event queue.

View File

@ -46,7 +46,7 @@ extern "C" {
/** /**
* This is the timeout value which corresponds to never time out. * This is the timeout value which corresponds to never time out.
*/ */
#define SDL_MUTEX_MAXWAIT (~(Uint32)0) #define SDL_MUTEX_MAXWAIT -1
/** /**
@ -194,6 +194,7 @@ typedef struct SDL_semaphore SDL_sem;
* \sa SDL_SemValue * \sa SDL_SemValue
* \sa SDL_SemWait * \sa SDL_SemWait
* \sa SDL_SemWaitTimeout * \sa SDL_SemWaitTimeout
* \sa SDL_SemWaitTimeoutNS
*/ */
extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value); extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value);
@ -213,8 +214,9 @@ extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value);
* \sa SDL_SemValue * \sa SDL_SemValue
* \sa SDL_SemWait * \sa SDL_SemWait
* \sa SDL_SemWaitTimeout * \sa SDL_SemWaitTimeout
* \sa SDL_SemWaitTimeoutNS
*/ */
extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem * sem); extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem);
/** /**
* Wait until a semaphore has a positive value and then decrements it. * Wait until a semaphore has a positive value and then decrements it.
@ -240,8 +242,9 @@ extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem * sem);
* \sa SDL_SemValue * \sa SDL_SemValue
* \sa SDL_SemWait * \sa SDL_SemWait
* \sa SDL_SemWaitTimeout * \sa SDL_SemWaitTimeout
* \sa SDL_SemWaitTimeoutNS
*/ */
extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem * sem); extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem);
/** /**
* See if a semaphore has a positive value and decrement it if it does. * See if a semaphore has a positive value and decrement it if it does.
@ -264,8 +267,9 @@ extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem * sem);
* \sa SDL_SemValue * \sa SDL_SemValue
* \sa SDL_SemWait * \sa SDL_SemWait
* \sa SDL_SemWaitTimeout * \sa SDL_SemWaitTimeout
* \sa SDL_SemWaitTimeoutNS
*/ */
extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem); extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem);
/** /**
* Wait until a semaphore has a positive value and then decrements it. * Wait until a semaphore has a positive value and then decrements it.
@ -276,7 +280,7 @@ extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem);
* successful it will atomically decrement the semaphore value. * successful it will atomically decrement the semaphore value.
* *
* \param sem the semaphore to wait on * \param sem the semaphore to wait on
* \param timeout the length of the timeout, in milliseconds * \param timeoutMS the length of the timeout, in milliseconds
* \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not
* succeed in the allotted time, or a negative error code on failure; * succeed in the allotted time, or a negative error code on failure;
* call SDL_GetError() for more information. * call SDL_GetError() for more information.
@ -289,8 +293,35 @@ extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem);
* \sa SDL_SemTryWait * \sa SDL_SemTryWait
* \sa SDL_SemValue * \sa SDL_SemValue
* \sa SDL_SemWait * \sa SDL_SemWait
* \sa SDL_SemWaitTimeoutNS
*/ */
extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout); extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Sint32 timeoutMS);
/**
* Wait until a semaphore has a positive value and then decrements it.
*
* This function suspends the calling thread until either the semaphore
* pointed to by `sem` has a positive value, the call is interrupted by a
* signal or error, or the specified time has elapsed. If the call is
* successful it will atomically decrement the semaphore value.
*
* \param sem the semaphore to wait on
* \param timeoutNS the length of the timeout, in nanoseconds
* \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not
* succeed in the allotted time, or a negative error code on failure;
* call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_CreateSemaphore
* \sa SDL_DestroySemaphore
* \sa SDL_SemPost
* \sa SDL_SemTryWait
* \sa SDL_SemValue
* \sa SDL_SemWait
* \sa SDL_SemWaitTimeout
*/
extern DECLSPEC int SDLCALL SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS);
/** /**
* Atomically increment a semaphore's value and wake waiting threads. * Atomically increment a semaphore's value and wake waiting threads.
@ -308,7 +339,7 @@ extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout);
* \sa SDL_SemWait * \sa SDL_SemWait
* \sa SDL_SemWaitTimeout * \sa SDL_SemWaitTimeout
*/ */
extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem); extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem);
/** /**
* Get the current value of a semaphore. * Get the current value of a semaphore.
@ -320,7 +351,7 @@ extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem);
* *
* \sa SDL_CreateSemaphore * \sa SDL_CreateSemaphore
*/ */
extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem * sem); extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem);
/* @} *//* Semaphore functions */ /* @} *//* Semaphore functions */
@ -346,6 +377,7 @@ typedef struct SDL_cond SDL_cond;
* \sa SDL_CondSignal * \sa SDL_CondSignal
* \sa SDL_CondWait * \sa SDL_CondWait
* \sa SDL_CondWaitTimeout * \sa SDL_CondWaitTimeout
* \sa SDL_CondWaitTimeoutNS
* \sa SDL_DestroyCond * \sa SDL_DestroyCond
*/ */
extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void); extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void);
@ -361,9 +393,10 @@ extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void);
* \sa SDL_CondSignal * \sa SDL_CondSignal
* \sa SDL_CondWait * \sa SDL_CondWait
* \sa SDL_CondWaitTimeout * \sa SDL_CondWaitTimeout
* \sa SDL_CondWaitTimeoutNS
* \sa SDL_CreateCond * \sa SDL_CreateCond
*/ */
extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond); extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond);
/** /**
* Restart one of the threads that are waiting on the condition variable. * Restart one of the threads that are waiting on the condition variable.
@ -377,10 +410,11 @@ extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond);
* \sa SDL_CondBroadcast * \sa SDL_CondBroadcast
* \sa SDL_CondWait * \sa SDL_CondWait
* \sa SDL_CondWaitTimeout * \sa SDL_CondWaitTimeout
* \sa SDL_CondWaitTimeoutNS
* \sa SDL_CreateCond * \sa SDL_CreateCond
* \sa SDL_DestroyCond * \sa SDL_DestroyCond
*/ */
extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond); extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond);
/** /**
* Restart all threads that are waiting on the condition variable. * Restart all threads that are waiting on the condition variable.
@ -394,10 +428,11 @@ extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond);
* \sa SDL_CondSignal * \sa SDL_CondSignal
* \sa SDL_CondWait * \sa SDL_CondWait
* \sa SDL_CondWaitTimeout * \sa SDL_CondWaitTimeout
* \sa SDL_CondWaitTimeoutNS
* \sa SDL_CreateCond * \sa SDL_CreateCond
* \sa SDL_DestroyCond * \sa SDL_DestroyCond
*/ */
extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond); extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond);
/** /**
* Wait until a condition variable is signaled. * Wait until a condition variable is signaled.
@ -422,10 +457,11 @@ extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond);
* \sa SDL_CondBroadcast * \sa SDL_CondBroadcast
* \sa SDL_CondSignal * \sa SDL_CondSignal
* \sa SDL_CondWaitTimeout * \sa SDL_CondWaitTimeout
* \sa SDL_CondWaitTimeoutNS
* \sa SDL_CreateCond * \sa SDL_CreateCond
* \sa SDL_DestroyCond * \sa SDL_DestroyCond
*/ */
extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex); extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex);
/** /**
* Wait until a condition variable is signaled or a certain time has passed. * Wait until a condition variable is signaled or a certain time has passed.
@ -440,7 +476,7 @@ extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);
* *
* \param cond the condition variable to wait on * \param cond the condition variable to wait on
* \param mutex the mutex used to coordinate thread access * \param mutex the mutex used to coordinate thread access
* \param ms the maximum time to wait, in milliseconds, or `SDL_MUTEX_MAXWAIT` * \param timeoutMS the maximum time to wait, in milliseconds, or `SDL_MUTEX_MAXWAIT`
* to wait indefinitely * to wait indefinitely
* \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if
* the condition is not signaled in the allotted time, or a negative * the condition is not signaled in the allotted time, or a negative
@ -451,11 +487,42 @@ extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);
* \sa SDL_CondBroadcast * \sa SDL_CondBroadcast
* \sa SDL_CondSignal * \sa SDL_CondSignal
* \sa SDL_CondWait * \sa SDL_CondWait
* \sa SDL_CondWaitTimeoutNS
* \sa SDL_CreateCond * \sa SDL_CreateCond
* \sa SDL_DestroyCond * \sa SDL_DestroyCond
*/ */
extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond, extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond,
SDL_mutex * mutex, Uint32 ms); SDL_mutex *mutex, Sint32 timeoutMS);
/**
* Wait until a condition variable is signaled or a certain time has passed.
*
* This function unlocks the specified `mutex` and waits for another thread to
* call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
* `cond`, or for the specified time to elapse. Once the condition variable is
* signaled or the time elapsed, the mutex is re-locked and the function
* returns.
*
* The mutex must be locked before calling this function.
*
* \param cond the condition variable to wait on
* \param mutex the mutex used to coordinate thread access
* \param timeoutNS the maximum time to wait, in nanoseconds, or `SDL_MUTEX_MAXWAIT` to wait indefinitely
* \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if
* the condition is not signaled in the allotted time, or a negative
* error code on failure; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_CondBroadcast
* \sa SDL_CondSignal
* \sa SDL_CondWait
* \sa SDL_CondWaitTimeout
* \sa SDL_CreateCond
* \sa SDL_DestroyCond
*/
extern DECLSPEC int SDLCALL SDL_CondWaitTimeoutNS(SDL_cond *cond,
SDL_mutex *mutex, Sint64 timeoutNS);
/* @} *//* Condition variable functions */ /* @} *//* Condition variable functions */

View File

@ -38,72 +38,37 @@ extern "C" {
#endif #endif
/** /**
* Get the number of milliseconds since SDL library initialization. * SDL time constants
*
* This value wraps if the program runs for more than ~49 days.
*
* This function is not recommended as of SDL 2.0.18; use SDL_GetTicks64()
* instead, where the value doesn't wrap every ~49 days. There are places in
* SDL where we provide a 32-bit timestamp that can not change without
* breaking binary compatibility, though, so this function isn't officially
* deprecated.
*
* \returns an unsigned 32-bit value representing the number of milliseconds
* since the SDL library initialized.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_TICKS_PASSED
*/ */
extern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void); #define SDL_MS_PER_SECOND 1000
#define SDL_US_PER_SECOND 1000000
#define SDL_NS_PER_SECOND 1000000000LLU
#define SDL_NS_PER_MS 1000000
#define SDL_NS_PER_US 1000
#define SDL_MS_TO_NS(MS) (((Uint64)(MS)) * SDL_NS_PER_MS)
#define SDL_NS_TO_MS(NS) ((NS) / SDL_NS_PER_MS)
#define SDL_US_TO_NS(US) (((Uint64)(US)) * SDL_NS_PER_US)
#define SDL_NS_TO_US(NS) ((NS) / SDL_NS_PER_US)
/** /**
* Get the number of milliseconds since SDL library initialization. * Get the number of milliseconds since SDL library initialization.
* *
* Note that you should not use the SDL_TICKS_PASSED macro with values
* returned by this function, as that macro does clever math to compensate for
* the 32-bit overflow every ~49 days that SDL_GetTicks() suffers from. 64-bit
* values from this function can be safely compared directly.
*
* For example, if you want to wait 100 ms, you could do this:
*
* ```c
* const Uint64 timeout = SDL_GetTicks64() + 100;
* while (SDL_GetTicks64() < timeout) {
* // ... do work until timeout has elapsed
* }
* ```
*
* \returns an unsigned 64-bit value representing the number of milliseconds * \returns an unsigned 64-bit value representing the number of milliseconds
* since the SDL library initialized. * since the SDL library initialized.
* *
* \since This function is available since SDL 3.0.0. * \since This function is available since SDL 3.0.0.
*/ */
extern DECLSPEC Uint64 SDLCALL SDL_GetTicks64(void); extern DECLSPEC Uint64 SDLCALL SDL_GetTicks(void);
/** /**
* Compare 32-bit SDL ticks values, and return true if `A` has passed `B`. * Get the number of nanoseconds since SDL library initialization.
* *
* This should be used with results from SDL_GetTicks(), as this macro * \returns an unsigned 64-bit value representing the number of nanoseconds
* attempts to deal with the 32-bit counter wrapping back to zero every ~49 * since the SDL library initialized.
* days, but should _not_ be used with SDL_GetTicks64(), which does not have
* that problem.
* *
* For example, with SDL_GetTicks(), if you want to wait 100 ms, you could * \since This function is available since SDL 3.0.0.
* do this:
*
* ```c
* const Uint32 timeout = SDL_GetTicks() + 100;
* while (!SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
* // ... do work until timeout has elapsed
* }
* ```
*
* Note that this does not handle tick differences greater
* than 2^31 so take care when using the above kind of code
* with large timeout delays (tens of days).
*/ */
#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0) extern DECLSPEC Uint64 SDLCALL SDL_GetTicksNS(void);
/** /**
* Get the current value of the high resolution counter. * Get the current value of the high resolution counter.
@ -146,15 +111,28 @@ extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void);
*/ */
extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms); extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);
/**
* Wait a specified number of nanoseconds before returning.
*
* This function waits a specified number of nanoseconds before returning. It
* waits at least the specified time, but possibly longer due to OS
* scheduling.
*
* \param ns the number of nanoseconds to delay
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC void SDLCALL SDL_DelayNS(Uint64 ns);
/** /**
* Function prototype for the timer callback function. * Function prototype for the timer callback function.
* *
* The callback function is passed the current timer interval and returns * The callback function is passed the current timer interval and returns
* the next timer interval. If the returned value is the same as the one * the next timer interval, in milliseconds. If the returned value is the same as the one
* passed in, the periodic alarm continues, otherwise a new alarm is * passed in, the periodic alarm continues, otherwise a new alarm is
* scheduled. If the callback returns 0, the periodic alarm is cancelled. * scheduled. If the callback returns 0, the periodic alarm is cancelled.
*/ */
typedef Uint32 (SDLCALL * SDL_TimerCallback) (Uint32 interval, void *param); typedef Uint32 (SDLCALL *SDL_TimerCallback)(Uint32 interval, void *param);
/** /**
* Definition of the timer ID type. * Definition of the timer ID type.
@ -179,7 +157,7 @@ typedef int SDL_TimerID;
* iteration. * iteration.
* *
* Timing may be inexact due to OS scheduling. Be sure to note the current * Timing may be inexact due to OS scheduling. Be sure to note the current
* time with SDL_GetTicks() or SDL_GetPerformanceCounter() in case your * time with SDL_GetTicksNS() or SDL_GetPerformanceCounter() in case your
* callback needs to adjust for variances. * callback needs to adjust for variances.
* *
* \param interval the timer delay, in milliseconds, passed to `callback` * \param interval the timer delay, in milliseconds, passed to `callback`

View File

@ -909,8 +909,8 @@ static int SDLCALL ALSA_HotplugThread(void *arg)
while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) { while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) {
/* Block awhile before checking again, unless we're told to stop. */ /* Block awhile before checking again, unless we're told to stop. */
const Uint32 ticks = SDL_GetTicks() + 5000; const Uint64 ticks = SDL_GetTicks() + 5000;
while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && !SDL_TICKS_PASSED(SDL_GetTicks(), ticks)) { while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && SDL_GetTicks() < ticks) {
SDL_Delay(100); SDL_Delay(100);
} }

View File

@ -32,7 +32,7 @@
#endif #endif
#include <errno.h> #include <errno.h>
int SDL_IOReady(int fd, int flags, int timeoutMS) int SDL_IOReady(int fd, int flags, Sint64 timeoutNS)
{ {
int result; int result;
@ -42,6 +42,7 @@ int SDL_IOReady(int fd, int flags, int timeoutMS)
do { do {
#ifdef HAVE_POLL #ifdef HAVE_POLL
struct pollfd info; struct pollfd info;
int timeoutMS;
info.fd = fd; info.fd = fd;
info.events = 0; info.events = 0;
@ -51,6 +52,14 @@ int SDL_IOReady(int fd, int flags, int timeoutMS)
if (flags & SDL_IOR_WRITE) { if (flags & SDL_IOR_WRITE) {
info.events |= POLLOUT; info.events |= POLLOUT;
} }
/* FIXME: Add support for ppoll() for nanosecond precision */
if (timeoutNS > 0) {
timeoutMS = (int)SDL_NS_TO_MS(timeoutNS);
} else if (timeoutNS == 0) {
timeoutMS = 0;
} else {
timeoutMS = -1;
}
result = poll(&info, 1, timeoutMS); result = poll(&info, 1, timeoutMS);
#else #else
fd_set rfdset, *rfdp = NULL; fd_set rfdset, *rfdp = NULL;
@ -71,9 +80,9 @@ int SDL_IOReady(int fd, int flags, int timeoutMS)
wfdp = &wfdset; wfdp = &wfdset;
} }
if (timeoutMS >= 0) { if (timeoutNS >= 0) {
tv.tv_sec = timeoutMS / 1000; tv.tv_sec = (timeoutNS / SDL_NS_PER_SECOND);
tv.tv_usec = (timeoutMS % 1000) * 1000; tv.tv_usec = SDL_NS_TO_US(timeoutNS % SDL_NS_PER_SECOND);
tvp = &tv; tvp = &tv;
} }

View File

@ -28,7 +28,7 @@
#define SDL_IOR_WRITE 0x2 #define SDL_IOR_WRITE 0x2
#define SDL_IOR_NO_RETRY 0x4 #define SDL_IOR_NO_RETRY 0x4
extern int SDL_IOReady(int fd, int flags, int timeoutMS); extern int SDL_IOReady(int fd, int flags, Sint64 timeoutNS);
#endif /* SDL_poll_h_ */ #endif /* SDL_poll_h_ */

View File

@ -809,7 +809,6 @@
#define SDL_asprintf SDL_asprintf_REAL #define SDL_asprintf SDL_asprintf_REAL
#define SDL_vasprintf SDL_vasprintf_REAL #define SDL_vasprintf SDL_vasprintf_REAL
#define SDL_GetWindowICCProfile SDL_GetWindowICCProfile_REAL #define SDL_GetWindowICCProfile SDL_GetWindowICCProfile_REAL
#define SDL_GetTicks64 SDL_GetTicks64_REAL
#define SDL_LinuxSetThreadPriorityAndPolicy SDL_LinuxSetThreadPriorityAndPolicy_REAL #define SDL_LinuxSetThreadPriorityAndPolicy SDL_LinuxSetThreadPriorityAndPolicy_REAL
#define SDL_GameControllerGetAppleSFSymbolsNameForButton SDL_GameControllerGetAppleSFSymbolsNameForButton_REAL #define SDL_GameControllerGetAppleSFSymbolsNameForButton SDL_GameControllerGetAppleSFSymbolsNameForButton_REAL
#define SDL_GameControllerGetAppleSFSymbolsNameForAxis SDL_GameControllerGetAppleSFSymbolsNameForAxis_REAL #define SDL_GameControllerGetAppleSFSymbolsNameForAxis SDL_GameControllerGetAppleSFSymbolsNameForAxis_REAL
@ -891,3 +890,8 @@
#define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL #define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL
#define SDL_GetWindowWMInfo SDL_GetWindowWMInfo_REAL #define SDL_GetWindowWMInfo SDL_GetWindowWMInfo_REAL
#define SDL_memset4 SDL_memset4_REAL #define SDL_memset4 SDL_memset4_REAL
#define SDL_WaitEventTimeoutNS SDL_WaitEventTimeoutNS_REAL
#define SDL_SemWaitTimeoutNS SDL_SemWaitTimeoutNS_REAL
#define SDL_CondWaitTimeoutNS SDL_CondWaitTimeoutNS_REAL
#define SDL_GetTicksNS SDL_GetTicksNS_REAL
#define SDL_DelayNS SDL_DelayNS_REAL

View File

@ -147,7 +147,7 @@ SDL_DYNAPI_PROC(void,SDL_FlushEvent,(Uint32 a),(a),)
SDL_DYNAPI_PROC(void,SDL_FlushEvents,(Uint32 a, Uint32 b),(a,b),) SDL_DYNAPI_PROC(void,SDL_FlushEvents,(Uint32 a, Uint32 b),(a,b),)
SDL_DYNAPI_PROC(int,SDL_PollEvent,(SDL_Event *a),(a),return) SDL_DYNAPI_PROC(int,SDL_PollEvent,(SDL_Event *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_WaitEvent,(SDL_Event *a),(a),return) SDL_DYNAPI_PROC(int,SDL_WaitEvent,(SDL_Event *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_WaitEventTimeout,(SDL_Event *a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_WaitEventTimeout,(SDL_Event *a, Sint32 b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_PushEvent,(SDL_Event *a),(a),return) SDL_DYNAPI_PROC(int,SDL_PushEvent,(SDL_Event *a),(a),return)
SDL_DYNAPI_PROC(void,SDL_SetEventFilter,(SDL_EventFilter a, void *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_SetEventFilter,(SDL_EventFilter a, void *b),(a,b),)
SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return)
@ -291,7 +291,7 @@ SDL_DYNAPI_PROC(SDL_sem*,SDL_CreateSemaphore,(Uint32 a),(a),return)
SDL_DYNAPI_PROC(void,SDL_DestroySemaphore,(SDL_sem *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroySemaphore,(SDL_sem *a),(a),)
SDL_DYNAPI_PROC(int,SDL_SemWait,(SDL_sem *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SemWait,(SDL_sem *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SemTryWait,(SDL_sem *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SemTryWait,(SDL_sem *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SemWaitTimeout,(SDL_sem *a, Uint32 b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SemWaitTimeout,(SDL_sem *a, Sint32 b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_SemPost,(SDL_sem *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SemPost,(SDL_sem *a),(a),return)
SDL_DYNAPI_PROC(Uint32,SDL_SemValue,(SDL_sem *a),(a),return) SDL_DYNAPI_PROC(Uint32,SDL_SemValue,(SDL_sem *a),(a),return)
SDL_DYNAPI_PROC(SDL_cond*,SDL_CreateCond,(void),(),return) SDL_DYNAPI_PROC(SDL_cond*,SDL_CreateCond,(void),(),return)
@ -299,7 +299,7 @@ SDL_DYNAPI_PROC(void,SDL_DestroyCond,(SDL_cond *a),(a),)
SDL_DYNAPI_PROC(int,SDL_CondSignal,(SDL_cond *a),(a),return) SDL_DYNAPI_PROC(int,SDL_CondSignal,(SDL_cond *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_CondBroadcast,(SDL_cond *a),(a),return) SDL_DYNAPI_PROC(int,SDL_CondBroadcast,(SDL_cond *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_CondWait,(SDL_cond *a, SDL_mutex *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_CondWait,(SDL_cond *a, SDL_mutex *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_CondWaitTimeout,(SDL_cond *a, SDL_mutex *b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_CondWaitTimeout,(SDL_cond *a, SDL_mutex *b, Sint32 c),(a,b,c),return)
SDL_DYNAPI_PROC(const char*,SDL_GetPixelFormatName,(Uint32 a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetPixelFormatName,(Uint32 a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_PixelFormatEnumToMasks,(Uint32 a, int *b, Uint32 *c, Uint32 *d, Uint32 *e, Uint32 *f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(SDL_bool,SDL_PixelFormatEnumToMasks,(Uint32 a, int *b, Uint32 *c, Uint32 *d, Uint32 *e, Uint32 *f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(Uint32,SDL_MasksToPixelFormatEnum,(int a, Uint32 b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(Uint32,SDL_MasksToPixelFormatEnum,(int a, Uint32 b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),return)
@ -500,7 +500,7 @@ SDL_DYNAPI_PROC(void,SDL_DetachThread,(SDL_Thread *a),(a),)
SDL_DYNAPI_PROC(SDL_TLSID,SDL_TLSCreate,(void),(),return) SDL_DYNAPI_PROC(SDL_TLSID,SDL_TLSCreate,(void),(),return)
SDL_DYNAPI_PROC(void*,SDL_TLSGet,(SDL_TLSID a),(a),return) SDL_DYNAPI_PROC(void*,SDL_TLSGet,(SDL_TLSID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_TLSSet,(SDL_TLSID a, const void *b, void (SDLCALL *c)(void*)),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_TLSSet,(SDL_TLSID a, const void *b, void (SDLCALL *c)(void*)),(a,b,c),return)
SDL_DYNAPI_PROC(Uint32,SDL_GetTicks,(void),(),return) SDL_DYNAPI_PROC(Uint64,SDL_GetTicks,(void),(),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceCounter,(void),(),return) SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceCounter,(void),(),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceFrequency,(void),(),return) SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceFrequency,(void),(),return)
SDL_DYNAPI_PROC(void,SDL_Delay,(Uint32 a),(a),) SDL_DYNAPI_PROC(void,SDL_Delay,(Uint32 a),(a),)
@ -874,7 +874,6 @@ SDL_DYNAPI_PROC(int,SDL_asprintf,(char **a, SDL_PRINTF_FORMAT_STRING const char
#endif #endif
SDL_DYNAPI_PROC(int,SDL_vasprintf,(char **a, const char *b, va_list c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_vasprintf,(char **a, const char *b, va_list c),(a,b,c),return)
SDL_DYNAPI_PROC(void*,SDL_GetWindowICCProfile,(SDL_Window *a, size_t *b),(a,b),return) SDL_DYNAPI_PROC(void*,SDL_GetWindowICCProfile,(SDL_Window *a, size_t *b),(a,b),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetTicks64,(void),(),return)
#ifdef __LINUX__ #ifdef __LINUX__
SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriorityAndPolicy,(Sint64 a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriorityAndPolicy,(Sint64 a, int b, int c),(a,b,c),return)
#endif #endif
@ -967,3 +966,8 @@ SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),)
#endif #endif
SDL_DYNAPI_PROC(int,SDL_GetWindowWMInfo,(SDL_Window *a, SDL_SysWMinfo *b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetWindowWMInfo,(SDL_Window *a, SDL_SysWMinfo *b, Uint32 c),(a,b,c),return)
SDL_DYNAPI_PROC(void*,SDL_memset4,(void *a, Uint32 b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(void*,SDL_memset4,(void *a, Uint32 b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_WaitEventTimeoutNS,(SDL_Event *a, Sint64 b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_SemWaitTimeoutNS,(SDL_sem *a, Sint64 b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_CondWaitTimeoutNS,(SDL_cond *a, SDL_mutex *b, Sint64 c),(a,b,c),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetTicksNS,(void),(),return)
SDL_DYNAPI_PROC(void,SDL_DelayNS,(Uint64 a),(a),)

View File

@ -42,7 +42,7 @@
#define SDL_MAX_QUEUED_EVENTS 65535 #define SDL_MAX_QUEUED_EVENTS 65535
/* Determines how often we wake to call SDL_PumpEvents() in SDL_WaitEventTimeout_Device() */ /* Determines how often we wake to call SDL_PumpEvents() in SDL_WaitEventTimeout_Device() */
#define PERIODIC_POLL_INTERVAL_MS 3000 #define PERIODIC_POLL_INTERVAL_NS (3 * SDL_NS_PER_SECOND)
typedef struct SDL_EventWatcher typedef struct SDL_EventWatcher
{ {
@ -963,7 +963,7 @@ void SDL_PumpEvents()
int SDL_PollEvent(SDL_Event *event) int SDL_PollEvent(SDL_Event *event)
{ {
return SDL_WaitEventTimeout(event, 0); return SDL_WaitEventTimeoutNS(event, 0);
} }
static SDL_bool SDL_events_need_periodic_poll() static SDL_bool SDL_events_need_periodic_poll()
@ -983,9 +983,9 @@ static SDL_bool SDL_events_need_periodic_poll()
return need_periodic_poll; return need_periodic_poll;
} }
static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Event *event, Uint32 start, int timeout) static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Event *event, Uint64 start, Sint64 timeoutNS)
{ {
int loop_timeout = timeout; Sint64 loop_timeoutNS = timeoutNS;
SDL_bool need_periodic_poll = SDL_events_need_periodic_poll(); SDL_bool need_periodic_poll = SDL_events_need_periodic_poll();
for (;;) { for (;;) {
@ -1021,26 +1021,26 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
return 1; return 1;
} }
/* No events found in the queue, call WaitEventTimeout to wait for an event. */ /* No events found in the queue, call WaitEventTimeout to wait for an event. */
if (timeout > 0) { if (timeoutNS > 0) {
Uint32 elapsed = SDL_GetTicks() - start; Sint64 elapsed = SDL_GetTicksNS() - start;
if (elapsed >= (Uint32)timeout) { if (elapsed >= timeoutNS) {
/* Set wakeup_window to NULL without holding the lock. */ /* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL; _this->wakeup_window = NULL;
return 0; return 0;
} }
loop_timeout = (int)((Uint32)timeout - elapsed); loop_timeoutNS = (timeoutNS - elapsed);
} }
if (need_periodic_poll) { if (need_periodic_poll) {
if (loop_timeout >= 0) { if (loop_timeoutNS >= 0) {
loop_timeout = SDL_min(loop_timeout, PERIODIC_POLL_INTERVAL_MS); loop_timeoutNS = SDL_min(loop_timeoutNS, PERIODIC_POLL_INTERVAL_NS);
} else { } else {
loop_timeout = PERIODIC_POLL_INTERVAL_MS; loop_timeoutNS = PERIODIC_POLL_INTERVAL_NS;
} }
} }
status = _this->WaitEventTimeout(_this, loop_timeout); status = _this->WaitEventTimeout(_this, loop_timeoutNS);
/* Set wakeup_window to NULL without holding the lock. */ /* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL; _this->wakeup_window = NULL;
if (status == 0 && need_periodic_poll && loop_timeout == PERIODIC_POLL_INTERVAL_MS) { if (status == 0 && need_periodic_poll && loop_timeoutNS == PERIODIC_POLL_INTERVAL_NS) {
/* We may have woken up to poll. Try again */ /* We may have woken up to poll. Try again */
continue; continue;
} else if (status <= 0) { } else if (status <= 0) {
@ -1086,15 +1086,27 @@ static SDL_Window *SDL_find_active_window(SDL_VideoDevice *_this)
int SDL_WaitEvent(SDL_Event *event) int SDL_WaitEvent(SDL_Event *event)
{ {
return SDL_WaitEventTimeout(event, -1); return SDL_WaitEventTimeoutNS(event, -1);
} }
int SDL_WaitEventTimeout(SDL_Event *event, int timeout) int SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS)
{
Uint64 timeoutNS;
if (timeoutMS > 0) {
timeoutNS = SDL_MS_TO_NS(timeoutMS);
} else {
timeoutNS = timeoutMS;
}
return SDL_WaitEventTimeoutNS(event, timeoutNS);
}
int SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
{ {
SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *wakeup_window; SDL_Window *wakeup_window;
Uint32 start, expiration; Uint64 start, expiration;
SDL_bool include_sentinel = (timeout == 0) ? SDL_TRUE : SDL_FALSE; SDL_bool include_sentinel = (timeoutNS == 0) ? SDL_TRUE : SDL_FALSE;
int result; int result;
/* If there isn't a poll sentinel event pending, pump events and add one */ /* If there isn't a poll sentinel event pending, pump events and add one */
@ -1126,7 +1138,7 @@ int SDL_WaitEventTimeout(SDL_Event *event, int timeout)
} }
} }
if (result == 0) { if (result == 0) {
if (timeout == 0) { if (timeoutNS == 0) {
/* No events available, and not willing to wait */ /* No events available, and not willing to wait */
return 0; return 0;
} }
@ -1134,12 +1146,12 @@ int SDL_WaitEventTimeout(SDL_Event *event, int timeout)
/* Has existing events */ /* Has existing events */
return 1; return 1;
} }
/* We should have completely handled timeout == 0 above */ /* We should have completely handled timeoutNS == 0 above */
SDL_assert(timeout != 0); SDL_assert(timeoutNS != 0);
if (timeout > 0) { if (timeoutNS > 0) {
start = SDL_GetTicks(); start = SDL_GetTicksNS();
expiration = start + timeout; expiration = start + timeoutNS;
} else { } else {
start = 0; start = 0;
expiration = 0; expiration = 0;
@ -1149,7 +1161,7 @@ int SDL_WaitEventTimeout(SDL_Event *event, int timeout)
/* Look if a shown window is available to send the wakeup event. */ /* Look if a shown window is available to send the wakeup event. */
wakeup_window = SDL_find_active_window(_this); wakeup_window = SDL_find_active_window(_this);
if (wakeup_window) { if (wakeup_window) {
int status = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, start, timeout); int status = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, start, timeoutNS);
/* There may be implementation-defined conditions where the backend cannot /* There may be implementation-defined conditions where the backend cannot
reliably wait for the next event. If that happens, fall back to polling. */ reliably wait for the next event. If that happens, fall back to polling. */
@ -1165,7 +1177,7 @@ int SDL_WaitEventTimeout(SDL_Event *event, int timeout)
case -1: case -1:
return 0; return 0;
case 0: case 0:
if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) { if (timeoutNS > 0 && SDL_GetTicks() >= expiration) {
/* Timeout expired and no events */ /* Timeout expired and no events */
return 0; return 0;
} }
@ -1180,7 +1192,7 @@ int SDL_WaitEventTimeout(SDL_Event *event, int timeout)
int SDL_PushEvent(SDL_Event *event) int SDL_PushEvent(SDL_Event *event)
{ {
event->common.timestamp = SDL_GetTicks(); event->common.timestamp = SDL_GetTicksNS();
if (SDL_EventOK.callback || SDL_event_watchers_count > 0) { if (SDL_EventOK.callback || SDL_event_watchers_count > 0) {
if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) {

View File

@ -735,9 +735,9 @@ static int SDL_PrivateSendMouseButton(SDL_Window *window, SDL_MouseID mouseID, U
SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button); SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
if (clickstate) { if (clickstate) {
if (state == SDL_PRESSED) { if (state == SDL_PRESSED) {
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + mouse->double_click_time) || if (now >= (clickstate->last_timestamp + mouse->double_click_time) ||
SDL_abs(mouse->x - clickstate->last_x) > mouse->double_click_radius || SDL_abs(mouse->x - clickstate->last_x) > mouse->double_click_radius ||
SDL_abs(mouse->y - clickstate->last_y) > mouse->double_click_radius) { SDL_abs(mouse->y - clickstate->last_y) > mouse->double_click_radius) {
clickstate->click_count = 0; clickstate->click_count = 0;

View File

@ -38,7 +38,7 @@ typedef struct
typedef struct typedef struct
{ {
int last_x, last_y; int last_x, last_y;
Uint32 last_timestamp; Uint64 last_timestamp;
Uint8 click_count; Uint8 click_count;
} SDL_MouseClickState; } SDL_MouseClickState;

View File

@ -42,15 +42,8 @@ static int numhaptics = 0;
int SDL_SYS_HapticInit(void) int SDL_SYS_HapticInit(void)
{ {
/* Support for device connect/disconnect is API >= 16 only,
* so we poll every three seconds
* Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html
*/
static Uint32 timeout = 0;
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
timeout = SDL_GetTicks() + 3000;
Android_JNI_PollHapticDevices(); Android_JNI_PollHapticDevices();
}
return numhaptics; return numhaptics;
} }

View File

@ -46,7 +46,7 @@ struct haptic_hwdata
Uint8 userid; /* XInput userid index for this joystick */ Uint8 userid; /* XInput userid index for this joystick */
SDL_Thread *thread; SDL_Thread *thread;
SDL_mutex *mutex; SDL_mutex *mutex;
Uint32 stopTicks; Uint64 stopTicks;
SDL_atomic_t stopThread; SDL_atomic_t stopThread;
}; };

View File

@ -147,7 +147,7 @@ static int SDLCALL SDL_RunXInputHaptic(void *arg)
SDL_LockMutex(hwdata->mutex); SDL_LockMutex(hwdata->mutex);
/* If we're currently running and need to stop... */ /* If we're currently running and need to stop... */
if (hwdata->stopTicks) { if (hwdata->stopTicks) {
if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_TICKS_PASSED(SDL_GetTicks(), hwdata->stopTicks)) { if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_GetTicks() >= hwdata->stopTicks) {
XINPUT_VIBRATION vibration = { 0, 0 }; XINPUT_VIBRATION vibration = { 0, 0 };
hwdata->stopTicks = 0; hwdata->stopTicks = 0;
XINPUTSETSTATE(hwdata->userid, &vibration); XINPUTSETSTATE(hwdata->userid, &vibration);
@ -287,9 +287,6 @@ int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect,
/* do nothing. Effect runs for zero milliseconds. */ /* do nothing. Effect runs for zero milliseconds. */
} else { } else {
haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations); haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
if ((haptic->hwdata->stopTicks == SDL_HAPTIC_INFINITY) || (haptic->hwdata->stopTicks == 0)) {
haptic->hwdata->stopTicks = 1; /* fix edge cases. */
}
} }
SDL_UnlockMutex(haptic->hwdata->mutex); SDL_UnlockMutex(haptic->hwdata->mutex);
return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1; return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;

View File

@ -92,7 +92,7 @@ static struct
SDL_bool m_bInitialized; SDL_bool m_bInitialized;
Uint32 m_unDeviceChangeCounter; Uint32 m_unDeviceChangeCounter;
SDL_bool m_bCanGetNotifications; SDL_bool m_bCanGetNotifications;
Uint32 m_unLastDetect; Uint64 m_unLastDetect;
#if defined(__WIN32__) || defined(__WINGDK__) #if defined(__WIN32__) || defined(__WINGDK__)
SDL_threadID m_nThreadID; SDL_threadID m_nThreadID;
@ -367,8 +367,8 @@ HIDAPI_UpdateDiscovery()
if (!SDL_HIDAPI_discovery.m_bCanGetNotifications) { if (!SDL_HIDAPI_discovery.m_bCanGetNotifications) {
const Uint32 SDL_HIDAPI_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */ const Uint32 SDL_HIDAPI_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (!SDL_HIDAPI_discovery.m_unLastDetect || SDL_TICKS_PASSED(now, SDL_HIDAPI_discovery.m_unLastDetect + SDL_HIDAPI_DETECT_INTERVAL_MS)) { if (!SDL_HIDAPI_discovery.m_unLastDetect || now >= (SDL_HIDAPI_discovery.m_unLastDetect + SDL_HIDAPI_DETECT_INTERVAL_MS)) {
++SDL_HIDAPI_discovery.m_unDeviceChangeCounter; ++SDL_HIDAPI_discovery.m_unDeviceChangeCounter;
SDL_HIDAPI_discovery.m_unLastDetect = now; SDL_HIDAPI_discovery.m_unLastDetect = now;
} }

View File

@ -128,7 +128,7 @@ struct _SDL_GameController
SDL_ExtendedGameControllerBind *bindings; SDL_ExtendedGameControllerBind *bindings;
SDL_ExtendedGameControllerBind **last_match_axis; SDL_ExtendedGameControllerBind **last_match_axis;
Uint8 *last_hat_mask; Uint8 *last_hat_mask;
Uint32 guide_button_down; Uint64 guide_button_down;
struct _SDL_GameController *next; /* pointer to next game controller we have allocated */ struct _SDL_GameController *next; /* pointer to next game controller we have allocated */
}; };
@ -2901,7 +2901,7 @@ static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, S
#endif /* !SDL_EVENTS_DISABLED */ #endif /* !SDL_EVENTS_DISABLED */
if (button == SDL_CONTROLLER_BUTTON_GUIDE) { if (button == SDL_CONTROLLER_BUTTON_GUIDE) {
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (state == SDL_PRESSED) { if (state == SDL_PRESSED) {
gamecontroller->guide_button_down = now; gamecontroller->guide_button_down = now;
@ -2910,7 +2910,7 @@ static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, S
return 0; return 0;
} }
} else { } else {
if (!SDL_TICKS_PASSED(now, gamecontroller->guide_button_down + SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS)) { if (now < (gamecontroller->guide_button_down + SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS)) {
gamecontroller->joystick->delayed_guide_button = SDL_TRUE; gamecontroller->joystick->delayed_guide_button = SDL_TRUE;
return 0; return 0;
} }

View File

@ -966,9 +966,6 @@ int SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint
} else { } else {
result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble); result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble);
joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS; joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS;
if (!joystick->rumble_resend) {
joystick->rumble_resend = 1;
}
} }
if (result == 0) { if (result == 0) {
@ -977,9 +974,6 @@ int SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint
if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) { if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
if (!joystick->rumble_expiration) {
joystick->rumble_expiration = 1;
}
} else { } else {
joystick->rumble_expiration = 0; joystick->rumble_expiration = 0;
joystick->rumble_resend = 0; joystick->rumble_resend = 0;
@ -1010,9 +1004,6 @@ int SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint1
if ((left_rumble || right_rumble) && duration_ms) { if ((left_rumble || right_rumble) && duration_ms) {
joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
if (!joystick->trigger_rumble_expiration) {
joystick->trigger_rumble_expiration = 1;
}
} else { } else {
joystick->trigger_rumble_expiration = 0; joystick->trigger_rumble_expiration = 0;
} }
@ -1083,7 +1074,7 @@ int SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blu
green != joystick->led_green || green != joystick->led_green ||
blue != joystick->led_blue; blue != joystick->led_blue;
if (isfreshvalue || SDL_TICKS_PASSED(SDL_GetTicks(), joystick->led_expiration)) { if (isfreshvalue || SDL_GetTicks() >= joystick->led_expiration) {
result = joystick->driver->SetLED(joystick, red, green, blue); result = joystick->driver->SetLED(joystick, red, green, blue);
joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS; joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS;
} else { } else {
@ -1665,7 +1656,7 @@ int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
void SDL_JoystickUpdate(void) void SDL_JoystickUpdate(void)
{ {
int i; int i;
Uint32 now; Uint64 now;
SDL_Joystick *joystick; SDL_Joystick *joystick;
if (!SDL_WasInit(SDL_INIT_JOYSTICK)) { if (!SDL_WasInit(SDL_INIT_JOYSTICK)) {
@ -1689,14 +1680,12 @@ void SDL_JoystickUpdate(void)
} }
now = SDL_GetTicks(); now = SDL_GetTicks();
if (joystick->rumble_expiration && if (joystick->rumble_expiration && now >= joystick->rumble_expiration) {
SDL_TICKS_PASSED(now, joystick->rumble_expiration)) {
SDL_JoystickRumble(joystick, 0, 0, 0); SDL_JoystickRumble(joystick, 0, 0, 0);
joystick->rumble_resend = 0; joystick->rumble_resend = 0;
} }
if (joystick->rumble_resend && if (joystick->rumble_resend && now >= joystick->rumble_resend) {
SDL_TICKS_PASSED(now, joystick->rumble_resend)) {
joystick->driver->Rumble(joystick, joystick->low_frequency_rumble, joystick->high_frequency_rumble); joystick->driver->Rumble(joystick, joystick->low_frequency_rumble, joystick->high_frequency_rumble);
joystick->rumble_resend = now + SDL_RUMBLE_RESEND_MS; joystick->rumble_resend = now + SDL_RUMBLE_RESEND_MS;
if (joystick->rumble_resend == 0) { if (joystick->rumble_resend == 0) {
@ -1704,8 +1693,7 @@ void SDL_JoystickUpdate(void)
} }
} }
if (joystick->trigger_rumble_expiration && if (joystick->trigger_rumble_expiration && now >= joystick->trigger_rumble_expiration) {
SDL_TICKS_PASSED(now, joystick->trigger_rumble_expiration)) {
SDL_JoystickRumbleTriggers(joystick, 0, 0, 0); SDL_JoystickRumbleTriggers(joystick, 0, 0, 0);
} }
} }

View File

@ -102,17 +102,17 @@ struct _SDL_Joystick
Uint16 low_frequency_rumble; Uint16 low_frequency_rumble;
Uint16 high_frequency_rumble; Uint16 high_frequency_rumble;
Uint32 rumble_expiration; Uint64 rumble_expiration;
Uint32 rumble_resend; Uint64 rumble_resend;
Uint16 left_trigger_rumble; Uint16 left_trigger_rumble;
Uint16 right_trigger_rumble; Uint16 right_trigger_rumble;
Uint32 trigger_rumble_expiration; Uint64 trigger_rumble_expiration;
Uint8 led_red; Uint8 led_red;
Uint8 led_green; Uint8 led_green;
Uint8 led_blue; Uint8 led_blue;
Uint32 led_expiration; Uint64 led_expiration;
SDL_bool attached; SDL_bool attached;
SDL_bool is_game_controller; SDL_bool is_game_controller;

View File

@ -494,9 +494,10 @@ static void ANDROID_JoystickDetect(void)
* so we poll every three seconds * so we poll every three seconds
* Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html
*/ */
static Uint32 timeout = 0; static Uint64 timeout = 0;
if (!timeout || SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) { Uint64 now = SDL_GetTicks();
timeout = SDL_GetTicks() + 3000; if (!timeout || now >= timeout) {
timeout = now + 3000;
Android_JNI_PollInputDevices(); Android_JNI_PollInputDevices();
} }
} }

View File

@ -137,7 +137,7 @@ typedef struct
SDL_bool report_touchpad; SDL_bool report_touchpad;
SDL_bool hardware_calibration; SDL_bool hardware_calibration;
IMUCalibrationData calibration[6]; IMUCalibrationData calibration[6];
Uint32 last_packet; Uint64 last_packet;
int player_index; int player_index;
Uint8 rumble_left; Uint8 rumble_left;
Uint8 rumble_right; Uint8 rumble_right;
@ -1037,7 +1037,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
Uint8 data[USB_PACKET_LENGTH * 2]; Uint8 data[USB_PACKET_LENGTH * 2];
int size; int size;
int packet_count = 0; int packet_count = 0;
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (device->num_joysticks > 0) { if (device->num_joysticks > 0) {
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
@ -1089,7 +1089,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
if (device->is_bluetooth) { if (device->is_bluetooth) {
if (packet_count == 0) { if (packet_count == 0) {
/* Check to see if it looks like the device disconnected */ /* Check to see if it looks like the device disconnected */
if (SDL_TICKS_PASSED(now, ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) { if (now >= (ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) {
/* Send an empty output report to tickle the Bluetooth stack */ /* Send an empty output report to tickle the Bluetooth stack */
HIDAPI_DriverPS4_TickleBluetooth(device); HIDAPI_DriverPS4_TickleBluetooth(device);
} }
@ -1106,7 +1106,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
if (packet_count == 0) { if (packet_count == 0) {
if (device->num_joysticks > 0) { if (device->num_joysticks > 0) {
/* Check to see if it looks like the device disconnected */ /* Check to see if it looks like the device disconnected */
if (SDL_TICKS_PASSED(now, ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) { if (now >= (ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0]); HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
} }
} }

View File

@ -215,7 +215,7 @@ typedef struct
SDL_bool hardware_calibration; SDL_bool hardware_calibration;
IMUCalibrationData calibration[6]; IMUCalibrationData calibration[6];
Uint16 firmware_version; Uint16 firmware_version;
Uint32 last_packet; Uint64 last_packet;
int player_index; int player_index;
SDL_bool player_lights; SDL_bool player_lights;
Uint8 rumble_left; Uint8 rumble_left;
@ -703,7 +703,7 @@ static void HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device)
packet->rgucSensorTimestamp[1], packet->rgucSensorTimestamp[1],
packet->rgucSensorTimestamp[2], packet->rgucSensorTimestamp[2],
packet->rgucSensorTimestamp[3]); packet->rgucSensorTimestamp[3]);
if (SDL_TICKS_PASSED(timestamp, connection_complete)) { if ((Sint32)(connection_complete - timestamp) <= 0) {
led_reset_complete = SDL_TRUE; led_reset_complete = SDL_TRUE;
} }
} else { } else {
@ -1305,7 +1305,7 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
Uint8 data[USB_PACKET_LENGTH * 2]; Uint8 data[USB_PACKET_LENGTH * 2];
int size; int size;
int packet_count = 0; int packet_count = 0;
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (device->num_joysticks > 0) { if (device->num_joysticks > 0) {
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
@ -1365,7 +1365,7 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
if (device->is_bluetooth) { if (device->is_bluetooth) {
if (packet_count == 0) { if (packet_count == 0) {
/* Check to see if it looks like the device disconnected */ /* Check to see if it looks like the device disconnected */
if (SDL_TICKS_PASSED(now, ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) { if (now >= (ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) {
/* Send an empty output report to tickle the Bluetooth stack */ /* Send an empty output report to tickle the Bluetooth stack */
HIDAPI_DriverPS5_TickleBluetooth(device); HIDAPI_DriverPS5_TickleBluetooth(device);
} }

View File

@ -78,13 +78,13 @@ typedef struct
SDL_JoystickPowerLevel battery_level; SDL_JoystickPowerLevel battery_level;
SDL_bool charging; SDL_bool charging;
Uint32 last_battery_query_time; Uint64 last_battery_query_time;
SDL_bool rumble_report_pending; SDL_bool rumble_report_pending;
SDL_bool rumble_update_pending; SDL_bool rumble_update_pending;
Uint8 left_motor_amplitude; Uint8 left_motor_amplitude;
Uint8 right_motor_amplitude; Uint8 right_motor_amplitude;
Uint32 last_rumble_time; Uint64 last_rumble_time;
Uint8 last_state[USB_PACKET_LENGTH]; Uint8 last_state[USB_PACKET_LENGTH];
} SDL_DriverShield_Context; } SDL_DriverShield_Context;
@ -541,14 +541,14 @@ static SDL_bool HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device)
} }
/* Ask for battery state again if we're due for an update */ /* Ask for battery state again if we're due for an update */
if (joystick && SDL_TICKS_PASSED(SDL_GetTicks(), ctx->last_battery_query_time + BATTERY_POLL_INTERVAL_MS)) { if (joystick && SDL_GetTicks() >= (ctx->last_battery_query_time + BATTERY_POLL_INTERVAL_MS)) {
ctx->last_battery_query_time = SDL_GetTicks(); ctx->last_battery_query_time = SDL_GetTicks();
HIDAPI_DriverShield_SendCommand(device, CMD_BATTERY_STATE, NULL, 0); HIDAPI_DriverShield_SendCommand(device, CMD_BATTERY_STATE, NULL, 0);
} }
/* Retransmit rumble packets if they've lasted longer than the hardware supports */ /* Retransmit rumble packets if they've lasted longer than the hardware supports */
if ((ctx->left_motor_amplitude != 0 || ctx->right_motor_amplitude != 0) && if ((ctx->left_motor_amplitude != 0 || ctx->right_motor_amplitude != 0) &&
SDL_TICKS_PASSED(SDL_GetTicks(), ctx->last_rumble_time + RUMBLE_REFRESH_INTERVAL_MS)) { SDL_GetTicks() >= (ctx->last_rumble_time + RUMBLE_REFRESH_INTERVAL_MS)) {
ctx->rumble_update_pending = SDL_TRUE; ctx->rumble_update_pending = SDL_TRUE;
HIDAPI_DriverShield_SendNextRumble(device); HIDAPI_DriverShield_SendNextRumble(device);
} }

View File

@ -254,18 +254,18 @@ typedef struct
SwitchCommonOutputPacket_t m_RumblePacket; SwitchCommonOutputPacket_t m_RumblePacket;
Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength]; Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength];
SDL_bool m_bRumbleActive; SDL_bool m_bRumbleActive;
Uint32 m_unRumbleSent; Uint64 m_ulRumbleSent;
SDL_bool m_bRumblePending; SDL_bool m_bRumblePending;
SDL_bool m_bRumbleZeroPending; SDL_bool m_bRumbleZeroPending;
Uint32 m_unRumblePending; Uint32 m_unRumblePending;
SDL_bool m_bReportSensors; SDL_bool m_bReportSensors;
SDL_bool m_bHasSensorData; SDL_bool m_bHasSensorData;
Uint32 m_unLastInput; Uint64 m_ulLastInput;
Uint32 m_unLastIMUReset; Uint64 m_ulLastIMUReset;
Uint32 m_unIMUSampleTimestamp; Uint64 m_ulIMUSampleTimestampNS;
Uint32 m_unIMUSamples; Uint32 m_unIMUSamples;
Uint32 m_unIMUUpdateIntervalUS; Uint64 m_ulIMUUpdateIntervalNS;
Uint64 m_ulTimestampUS; Uint64 m_ulTimestampNS;
SDL_bool m_bVerticalMode; SDL_bool m_bVerticalMode;
SwitchInputOnlyControllerStatePacket_t m_lastInputOnlyState; SwitchInputOnlyControllerStatePacket_t m_lastInputOnlyState;
@ -329,8 +329,7 @@ static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int siz
static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID) static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID)
{ {
/* Average response time for messages is ~30ms */ /* Average response time for messages is ~30ms */
Uint32 TimeoutMs = 100; Uint64 endTicks = SDL_GetTicks() + 100;
Uint32 startTicks = SDL_GetTicks();
int nRead = 0; int nRead = 0;
while ((nRead = ReadInput(ctx)) != -1) { while ((nRead = ReadInput(ctx)) != -1) {
@ -345,7 +344,7 @@ static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Conte
SDL_Delay(1); SDL_Delay(1);
} }
if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) { if (SDL_GetTicks() >= endTicks) {
break; break;
} }
} }
@ -355,8 +354,7 @@ static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Conte
static SDL_bool ReadProprietaryReply(SDL_DriverSwitch_Context *ctx, ESwitchProprietaryCommandIDs expectedID) static SDL_bool ReadProprietaryReply(SDL_DriverSwitch_Context *ctx, ESwitchProprietaryCommandIDs expectedID)
{ {
/* Average response time for messages is ~30ms */ /* Average response time for messages is ~30ms */
Uint32 TimeoutMs = 100; Uint64 endTicks = SDL_GetTicks() + 100;
Uint32 startTicks = SDL_GetTicks();
int nRead = 0; int nRead = 0;
while ((nRead = ReadInput(ctx)) != -1) { while ((nRead = ReadInput(ctx)) != -1) {
@ -368,7 +366,7 @@ static SDL_bool ReadProprietaryReply(SDL_DriverSwitch_Context *ctx, ESwitchPropr
SDL_Delay(1); SDL_Delay(1);
} }
if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) { if (SDL_GetTicks() >= endTicks) {
break; break;
} }
} }
@ -536,7 +534,7 @@ static SDL_bool WriteRumble(SDL_DriverSwitch_Context *ctx)
ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF; ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF;
/* Refresh the rumble state periodically */ /* Refresh the rumble state periodically */
ctx->m_unRumbleSent = SDL_GetTicks(); ctx->m_ulRumbleSent = SDL_GetTicks();
return WritePacket(ctx, (Uint8 *)&ctx->m_RumblePacket, sizeof(ctx->m_RumblePacket)); return WritePacket(ctx, (Uint8 *)&ctx->m_RumblePacket, sizeof(ctx->m_RumblePacket));
} }
@ -1370,8 +1368,8 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
/* Set up for input */ /* Set up for input */
ctx->m_bSyncWrite = SDL_FALSE; ctx->m_bSyncWrite = SDL_FALSE;
ctx->m_unLastIMUReset = ctx->m_unLastInput = SDL_GetTicks(); ctx->m_ulLastIMUReset = ctx->m_ulLastInput = SDL_GetTicks();
ctx->m_unIMUUpdateIntervalUS = 5 * 1000; /* Start off at 5 ms update rate */ ctx->m_ulIMUUpdateIntervalNS = SDL_MS_TO_NS(5); /* Start off at 5 ms update rate */
/* Set up for vertical mode */ /* Set up for vertical mode */
ctx->m_bVerticalMode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, SDL_FALSE); ctx->m_bVerticalMode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, SDL_FALSE);
@ -1410,7 +1408,7 @@ static int HIDAPI_DriverSwitch_ActuallyRumbleJoystick(SDL_DriverSwitch_Context *
static int HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx) static int HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx)
{ {
if (!SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_unRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) { if (SDL_GetTicks() < (ctx->m_ulRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) {
return 0; return 0;
} }
@ -1419,7 +1417,7 @@ static int HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx)
Uint16 high_frequency_rumble = (Uint16)ctx->m_unRumblePending; Uint16 high_frequency_rumble = (Uint16)ctx->m_unRumblePending;
#ifdef DEBUG_RUMBLE #ifdef DEBUG_RUMBLE
SDL_Log("Sent pending rumble %d/%d, %d ms after previous rumble\n", low_frequency_rumble, high_frequency_rumble, SDL_GetTicks() - ctx->m_unRumbleSent); SDL_Log("Sent pending rumble %d/%d, %d ms after previous rumble\n", low_frequency_rumble, high_frequency_rumble, SDL_GetTicks() - ctx->m_ulRumbleSent);
#endif #endif
ctx->m_bRumblePending = SDL_FALSE; ctx->m_bRumblePending = SDL_FALSE;
ctx->m_unRumblePending = 0; ctx->m_unRumblePending = 0;
@ -1431,7 +1429,7 @@ static int HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx)
ctx->m_bRumbleZeroPending = SDL_FALSE; ctx->m_bRumbleZeroPending = SDL_FALSE;
#ifdef DEBUG_RUMBLE #ifdef DEBUG_RUMBLE
SDL_Log("Sent pending zero rumble, %d ms after previous rumble\n", SDL_GetTicks() - ctx->m_unRumbleSent); SDL_Log("Sent pending zero rumble, %d ms after previous rumble\n", SDL_GetTicks() - ctx->m_ulRumbleSent);
#endif #endif
return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, 0, 0); return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, 0, 0);
} }
@ -1463,7 +1461,7 @@ static int HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joy
} }
} }
if (!SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_unRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) { if (SDL_GetTicks() < (ctx->m_ulRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) {
if (low_frequency_rumble || high_frequency_rumble) { if (low_frequency_rumble || high_frequency_rumble) {
Uint32 unRumblePending = ((Uint32)low_frequency_rumble << 16) | high_frequency_rumble; Uint32 unRumblePending = ((Uint32)low_frequency_rumble << 16) | high_frequency_rumble;
@ -1522,7 +1520,7 @@ static int HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *devi
SetIMUEnabled(ctx, enabled); SetIMUEnabled(ctx, enabled);
ctx->m_bReportSensors = enabled; ctx->m_bReportSensors = enabled;
ctx->m_unIMUSamples = 0; ctx->m_unIMUSamples = 0;
ctx->m_unIMUSampleTimestamp = SDL_GetTicks(); ctx->m_ulIMUSampleTimestampNS = SDL_GetTicksNS();
return 0; return 0;
} }
@ -1988,22 +1986,22 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
/* We got three IMU samples, calculate the IMU update rate and timestamps */ /* We got three IMU samples, calculate the IMU update rate and timestamps */
ctx->m_unIMUSamples += 3; ctx->m_unIMUSamples += 3;
if (ctx->m_unIMUSamples >= IMU_UPDATE_RATE_SAMPLE_FREQUENCY) { if (ctx->m_unIMUSamples >= IMU_UPDATE_RATE_SAMPLE_FREQUENCY) {
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicksNS();
Uint32 elapsed = (now - ctx->m_unIMUSampleTimestamp); Uint64 elapsed = (now - ctx->m_ulIMUSampleTimestampNS);
if (elapsed > 0) { if (elapsed > 0) {
ctx->m_unIMUUpdateIntervalUS = (elapsed * 1000) / ctx->m_unIMUSamples; ctx->m_ulIMUUpdateIntervalNS = elapsed / ctx->m_unIMUSamples;
} }
ctx->m_unIMUSamples = 0; ctx->m_unIMUSamples = 0;
ctx->m_unIMUSampleTimestamp = now; ctx->m_ulIMUSampleTimestampNS = now;
} }
ctx->m_ulTimestampUS += ctx->m_unIMUUpdateIntervalUS; ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
timestamp[0] = ctx->m_ulTimestampUS; timestamp[0] = SDL_NS_TO_US(ctx->m_ulTimestampNS);
ctx->m_ulTimestampUS += ctx->m_unIMUUpdateIntervalUS; ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
timestamp[1] = ctx->m_ulTimestampUS; timestamp[1] = SDL_NS_TO_US(ctx->m_ulTimestampNS);
ctx->m_ulTimestampUS += ctx->m_unIMUUpdateIntervalUS; ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
timestamp[2] = ctx->m_ulTimestampUS; timestamp[2] = SDL_NS_TO_US(ctx->m_ulTimestampNS);
if (!ctx->device->parent || if (!ctx->device->parent ||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) { ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
@ -2042,10 +2040,10 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
} else if (ctx->m_bHasSensorData) { } else if (ctx->m_bHasSensorData) {
/* Uh oh, someone turned off the IMU? */ /* Uh oh, someone turned off the IMU? */
const Uint32 IMU_RESET_DELAY_MS = 3000; const int IMU_RESET_DELAY_MS = 3000;
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, ctx->m_unLastIMUReset + IMU_RESET_DELAY_MS)) { if (now >= (ctx->m_ulLastIMUReset + IMU_RESET_DELAY_MS)) {
SDL_HIDAPI_Device *device = ctx->device; SDL_HIDAPI_Device *device = ctx->device;
if (device->updating) { if (device->updating) {
@ -2057,7 +2055,7 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
if (device->updating) { if (device->updating) {
SDL_LockMutex(device->dev_lock); SDL_LockMutex(device->dev_lock);
} }
ctx->m_unLastIMUReset = now; ctx->m_ulLastIMUReset = now;
} }
} else { } else {
@ -2074,7 +2072,7 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
SDL_Joystick *joystick = NULL; SDL_Joystick *joystick = NULL;
int size; int size;
int packet_count = 0; int packet_count = 0;
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (device->num_joysticks > 0) { if (device->num_joysticks > 0) {
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
@ -2085,7 +2083,7 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
HIDAPI_DumpPacket("Nintendo Switch packet: size = %d", ctx->m_rgucReadBuffer, size); HIDAPI_DumpPacket("Nintendo Switch packet: size = %d", ctx->m_rgucReadBuffer, size);
#endif #endif
++packet_count; ++packet_count;
ctx->m_unLastInput = now; ctx->m_ulLastInput = now;
if (joystick == NULL) { if (joystick == NULL) {
continue; continue;
@ -2111,14 +2109,14 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
if (packet_count == 0) { if (packet_count == 0) {
if (!ctx->m_bInputOnly && !device->is_bluetooth && if (!ctx->m_bInputOnly && !device->is_bluetooth &&
ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
const Uint32 INPUT_WAIT_TIMEOUT_MS = 100; const int INPUT_WAIT_TIMEOUT_MS = 100;
if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { if (now >= (ctx->m_ulLastInput + INPUT_WAIT_TIMEOUT_MS)) {
/* Steam may have put the controller back into non-reporting mode */ /* Steam may have put the controller back into non-reporting mode */
WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE); WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE);
} }
} else if (device->is_bluetooth) { } else if (device->is_bluetooth) {
const Uint32 INPUT_WAIT_TIMEOUT_MS = 3000; const int INPUT_WAIT_TIMEOUT_MS = 3000;
if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { if (now >= (ctx->m_ulLastInput + INPUT_WAIT_TIMEOUT_MS)) {
/* Bluetooth may have disconnected, try reopening the controller */ /* Bluetooth may have disconnected, try reopening the controller */
size = -1; size = -1;
} }
@ -2128,9 +2126,9 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
if (ctx->m_bRumblePending || ctx->m_bRumbleZeroPending) { if (ctx->m_bRumblePending || ctx->m_bRumbleZeroPending) {
HIDAPI_DriverSwitch_SendPendingRumble(ctx); HIDAPI_DriverSwitch_SendPendingRumble(ctx);
} else if (ctx->m_bRumbleActive && } else if (ctx->m_bRumbleActive &&
SDL_TICKS_PASSED(now, ctx->m_unRumbleSent + RUMBLE_REFRESH_FREQUENCY_MS)) { now >= (ctx->m_ulRumbleSent + RUMBLE_REFRESH_FREQUENCY_MS)) {
#ifdef DEBUG_RUMBLE #ifdef DEBUG_RUMBLE
SDL_Log("Sent continuing rumble, %d ms after previous rumble\n", now - ctx->m_unRumbleSent); SDL_Log("Sent continuing rumble, %d ms after previous rumble\n", now - ctx->m_ulRumbleSent);
#endif #endif
WriteRumble(ctx); WriteRumble(ctx);
} }

View File

@ -142,9 +142,9 @@ typedef struct
Uint8 m_ucMotionPlusMode; Uint8 m_ucMotionPlusMode;
SDL_bool m_bReportSensors; SDL_bool m_bReportSensors;
Uint8 m_rgucReadBuffer[k_unWiiPacketDataLength]; Uint8 m_rgucReadBuffer[k_unWiiPacketDataLength];
Uint32 m_unLastInput; Uint64 m_ulLastInput;
Uint32 m_unLastStatus; Uint64 m_ulLastStatus;
Uint32 m_unNextMotionPlusCheck; Uint64 m_ulNextMotionPlusCheck;
SDL_bool m_bDisconnected; SDL_bool m_bDisconnected;
struct StickCalibrationData struct StickCalibrationData
@ -225,8 +225,7 @@ static SDL_bool WriteOutput(SDL_DriverWii_Context *ctx, const Uint8 *data, int s
static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs expectedID, SDL_bool (*isMine)(const Uint8 *)) static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs expectedID, SDL_bool (*isMine)(const Uint8 *))
{ {
Uint32 TimeoutMs = 250; /* Seeing successful reads after about 200 ms */ Uint64 endTicks = SDL_GetTicks() + 250; /* Seeing successful reads after about 200 ms */
Uint32 startTicks = SDL_GetTicks();
int nRead = 0; int nRead = 0;
while ((nRead = ReadInput(ctx)) != -1) { while ((nRead = ReadInput(ctx)) != -1) {
@ -235,7 +234,7 @@ static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs exp
return SDL_TRUE; return SDL_TRUE;
} }
} else { } else {
if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) { if (SDL_GetTicks() >= endTicks) {
break; break;
} }
SDL_Delay(1); SDL_Delay(1);
@ -443,10 +442,7 @@ static SDL_bool NeedsPeriodicMotionPlusCheck(SDL_DriverWii_Context *ctx, SDL_boo
static void SchedulePeriodicMotionPlusCheck(SDL_DriverWii_Context *ctx) static void SchedulePeriodicMotionPlusCheck(SDL_DriverWii_Context *ctx)
{ {
ctx->m_unNextMotionPlusCheck = SDL_GetTicks() + MOTION_PLUS_UPDATE_TIME_MS; ctx->m_ulNextMotionPlusCheck = SDL_GetTicks() + MOTION_PLUS_UPDATE_TIME_MS;
if (!ctx->m_unNextMotionPlusCheck) {
ctx->m_unNextMotionPlusCheck = 1;
}
} }
static void CheckMotionPlusConnection(SDL_DriverWii_Context *ctx) static void CheckMotionPlusConnection(SDL_DriverWii_Context *ctx)
@ -807,7 +803,7 @@ static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
} }
joystick->naxes = SDL_CONTROLLER_AXIS_MAX; joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
ctx->m_unLastInput = SDL_GetTicks(); ctx->m_ulLastInput = SDL_GetTicks();
return SDL_TRUE; return SDL_TRUE;
} }
@ -1433,7 +1429,7 @@ static void HandleStatus(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick)
* Motion Plus packets. * Motion Plus packets.
*/ */
if (NeedsPeriodicMotionPlusCheck(ctx, SDL_TRUE)) { if (NeedsPeriodicMotionPlusCheck(ctx, SDL_TRUE)) {
ctx->m_unNextMotionPlusCheck = SDL_GetTicks(); ctx->m_ulNextMotionPlusCheck = SDL_GetTicks();
} }
} else if (hadExtension != hasExtension) { } else if (hadExtension != hasExtension) {
@ -1568,7 +1564,7 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
SDL_Joystick *joystick = NULL; SDL_Joystick *joystick = NULL;
int size; int size;
Uint32 now; Uint64 now;
if (device->num_joysticks > 0) { if (device->num_joysticks > 0) {
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
@ -1582,7 +1578,7 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
if (joystick) { if (joystick) {
HandleInput(ctx, joystick); HandleInput(ctx, joystick);
} }
ctx->m_unLastInput = now; ctx->m_ulLastInput = now;
} }
/* Check to see if we've lost connection to the controller. /* Check to see if we've lost connection to the controller.
@ -1591,7 +1587,7 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
{ {
SDL_COMPILE_TIME_ASSERT(ENABLE_CONTINUOUS_REPORTING, ENABLE_CONTINUOUS_REPORTING); SDL_COMPILE_TIME_ASSERT(ENABLE_CONTINUOUS_REPORTING, ENABLE_CONTINUOUS_REPORTING);
} }
if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { if (now >= (ctx->m_ulLastInput + INPUT_WAIT_TIMEOUT_MS)) {
/* Bluetooth may have disconnected, try reopening the controller */ /* Bluetooth may have disconnected, try reopening the controller */
size = -1; size = -1;
} }
@ -1601,26 +1597,24 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_WiiUPro) { if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_WiiUPro) {
/* Check to see if the Motion Plus extension status has changed */ /* Check to see if the Motion Plus extension status has changed */
if (ctx->m_unNextMotionPlusCheck && if (ctx->m_ulNextMotionPlusCheck && now >= ctx->m_ulNextMotionPlusCheck) {
SDL_TICKS_PASSED(now, ctx->m_unNextMotionPlusCheck)) {
CheckMotionPlusConnection(ctx); CheckMotionPlusConnection(ctx);
if (NeedsPeriodicMotionPlusCheck(ctx, SDL_FALSE)) { if (NeedsPeriodicMotionPlusCheck(ctx, SDL_FALSE)) {
SchedulePeriodicMotionPlusCheck(ctx); SchedulePeriodicMotionPlusCheck(ctx);
} else { } else {
ctx->m_unNextMotionPlusCheck = 0; ctx->m_ulNextMotionPlusCheck = 0;
} }
} }
/* Request a status update periodically to make sure our battery value is up to date */ /* Request a status update periodically to make sure our battery value is up to date */
if (!ctx->m_unLastStatus || if (!ctx->m_ulLastStatus || now >= (ctx->m_ulLastStatus + STATUS_UPDATE_TIME_MS)) {
SDL_TICKS_PASSED(now, ctx->m_unLastStatus + STATUS_UPDATE_TIME_MS)) {
Uint8 data[2]; Uint8 data[2];
data[0] = k_eWiiOutputReportIDs_StatusRequest; data[0] = k_eWiiOutputReportIDs_StatusRequest;
data[1] = ctx->m_bRumbleActive; data[1] = ctx->m_bRumbleActive;
WriteOutput(ctx, data, sizeof(data), SDL_FALSE); WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
ctx->m_unLastStatus = now; ctx->m_ulLastStatus = now;
} }
} }
} }

View File

@ -117,9 +117,9 @@ typedef struct
SDL_bool bluetooth; SDL_bool bluetooth;
SDL_XboxOneInitState init_state; SDL_XboxOneInitState init_state;
int init_packet; int init_packet;
Uint32 start_time; Uint64 start_time;
Uint8 sequence; Uint8 sequence;
Uint32 send_time; Uint64 send_time;
SDL_bool has_guide_packet; SDL_bool has_guide_packet;
SDL_bool has_color_led; SDL_bool has_color_led;
SDL_bool has_paddles; SDL_bool has_paddles;
@ -132,7 +132,7 @@ typedef struct
Uint8 left_trigger_rumble; Uint8 left_trigger_rumble;
Uint8 right_trigger_rumble; Uint8 right_trigger_rumble;
SDL_XboxOneRumbleState rumble_state; SDL_XboxOneRumbleState rumble_state;
Uint32 rumble_time; Uint64 rumble_time;
SDL_bool rumble_pending; SDL_bool rumble_pending;
Uint8 last_state[USB_PACKET_LENGTH]; Uint8 last_state[USB_PACKET_LENGTH];
} SDL_DriverXboxOne_Context; } SDL_DriverXboxOne_Context;
@ -456,8 +456,8 @@ static int HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device)
} }
if (ctx->rumble_state == XBOX_ONE_RUMBLE_STATE_BUSY) { if (ctx->rumble_state == XBOX_ONE_RUMBLE_STATE_BUSY) {
const Uint32 RUMBLE_BUSY_TIME_MS = ctx->bluetooth ? 50 : 10; const int RUMBLE_BUSY_TIME_MS = ctx->bluetooth ? 50 : 10;
if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->rumble_time + RUMBLE_BUSY_TIME_MS)) { if (SDL_GetTicks() >= (ctx->rumble_time + RUMBLE_BUSY_TIME_MS)) {
ctx->rumble_time = 0; ctx->rumble_time = 0;
ctx->rumble_state = XBOX_ONE_RUMBLE_STATE_IDLE; ctx->rumble_state = XBOX_ONE_RUMBLE_STATE_IDLE;
} }
@ -1087,7 +1087,7 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateInitState(SDL_HIDAPI_Device *device,
#endif #endif
break; break;
case XBOX_ONE_INIT_STATE_NEGOTIATING: case XBOX_ONE_INIT_STATE_NEGOTIATING:
if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->send_time + CONTROLLER_NEGOTIATION_TIMEOUT_MS)) { if (SDL_GetTicks() >= (ctx->send_time + CONTROLLER_NEGOTIATION_TIMEOUT_MS)) {
/* We haven't heard anything, let's move on */ /* We haven't heard anything, let's move on */
#ifdef DEBUG_JOYSTICK #ifdef DEBUG_JOYSTICK
SDL_Log("Init sequence %d timed out after %u ms\n", ctx->init_packet, (SDL_GetTicks() - ctx->send_time)); SDL_Log("Init sequence %d timed out after %u ms\n", ctx->init_packet, (SDL_GetTicks() - ctx->send_time));
@ -1099,7 +1099,7 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateInitState(SDL_HIDAPI_Device *device,
} }
break; break;
case XBOX_ONE_INIT_STATE_PREPARE_INPUT: case XBOX_ONE_INIT_STATE_PREPARE_INPUT:
if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->send_time + CONTROLLER_PREPARE_INPUT_TIMEOUT_MS)) { if (SDL_GetTicks() >= (ctx->send_time + CONTROLLER_PREPARE_INPUT_TIMEOUT_MS)) {
#ifdef DEBUG_JOYSTICK #ifdef DEBUG_JOYSTICK
SDL_Log("Prepare input complete after %u ms\n", (SDL_GetTicks() - ctx->send_time)); SDL_Log("Prepare input complete after %u ms\n", (SDL_GetTicks() - ctx->send_time));
#endif #endif

View File

@ -119,7 +119,7 @@ static SDL_joylist_item *SDL_joylist_tail = NULL;
static int numjoysticks = 0; static int numjoysticks = 0;
static int inotify_fd = -1; static int inotify_fd = -1;
static Uint32 last_joy_detect_time; static Uint64 last_joy_detect_time;
static time_t last_input_dir_mtime; static time_t last_input_dir_mtime;
static void FixupDeviceInfoForMapping(int fd, struct input_id *inpid) static void FixupDeviceInfoForMapping(int fd, struct input_id *inpid)
@ -644,9 +644,9 @@ static int sort_entries(const void *_a, const void *_b)
static void LINUX_FallbackJoystickDetect(void) static void LINUX_FallbackJoystickDetect(void)
{ {
const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */ const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) { if (!last_joy_detect_time || now >= (last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
struct stat sb; struct stat sb;
/* Opening input devices can generate synchronous device I/O, so avoid it if we can */ /* Opening input devices can generate synchronous device I/O, so avoid it if we can */

View File

@ -129,7 +129,7 @@ struct joystick_hwdata
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING #ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
Uint64 match_state; /* Lowest 16 bits for button states, higher 24 for 6 4bit axes */ Uint64 match_state; /* Lowest 16 bits for button states, higher 24 for 6 4bit axes */
Uint32 last_state_packet; Uint64 last_state_packet;
#endif #endif
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT #ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
@ -167,7 +167,7 @@ static const Uint16 subscribed_devices[] = {
static struct static struct
{ {
Uint32 last_state_packet; Uint64 last_state_packet;
SDL_Joystick *joystick; SDL_Joystick *joystick;
SDL_Joystick *last_joystick; SDL_Joystick *last_joystick;
} guide_button_candidate; } guide_button_candidate;
@ -1808,7 +1808,7 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
if (!correlated) { if (!correlated) {
if (!guide_button_candidate.joystick || if (!guide_button_candidate.joystick ||
(ctx->last_state_packet && (!guide_button_candidate.last_state_packet || (ctx->last_state_packet && (!guide_button_candidate.last_state_packet ||
SDL_TICKS_PASSED(ctx->last_state_packet, guide_button_candidate.last_state_packet)))) { ctx->last_state_packet >= guide_button_candidate.last_state_packet))) {
guide_button_candidate.joystick = joystick; guide_button_candidate.joystick = joystick;
guide_button_candidate.last_state_packet = ctx->last_state_packet; guide_button_candidate.last_state_packet = ctx->last_state_packet;
} }

View File

@ -30,12 +30,12 @@
#if !TARGET_OS_TV #if !TARGET_OS_TV
/* turn off the battery monitor if it's been more than X ms since last check. */ /* turn off the battery monitor if it's been more than X ms since last check. */
static const int BATTERY_MONITORING_TIMEOUT = 3000; static const int BATTERY_MONITORING_TIMEOUT = 3000;
static Uint32 SDL_UIKitLastPowerInfoQuery = 0; static Uint64 SDL_UIKitLastPowerInfoQuery = 0;
void SDL_UIKit_UpdateBatteryMonitoring(void) void SDL_UIKit_UpdateBatteryMonitoring(void)
{ {
if (SDL_UIKitLastPowerInfoQuery) { if (SDL_UIKitLastPowerInfoQuery) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), SDL_UIKitLastPowerInfoQuery + BATTERY_MONITORING_TIMEOUT)) { if (SDL_GetTicks() >= (SDL_UIKitLastPowerInfoQuery + BATTERY_MONITORING_TIMEOUT)) {
UIDevice *uidev = [UIDevice currentDevice]; UIDevice *uidev = [UIDevice currentDevice];
SDL_assert([uidev isBatteryMonitoringEnabled] == YES); SDL_assert([uidev isBatteryMonitoringEnabled] == YES);
[uidev setBatteryMonitoringEnabled:NO]; [uidev setBatteryMonitoringEnabled:NO];

View File

@ -921,7 +921,7 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind
/* Pick a good default refresh rate */ /* Pick a good default refresh rate */
refresh_rate = 60; refresh_rate = 60;
} }
renderer->simulate_vsync_interval = (1000 / refresh_rate); renderer->simulate_vsync_interval_ns = (SDL_NS_PER_SECOND / refresh_rate);
} }
#endif /* !SDL_RENDER_DISABLED */ #endif /* !SDL_RENDER_DISABLED */
@ -4188,24 +4188,24 @@ int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
static void SDL_RenderSimulateVSync(SDL_Renderer *renderer) static void SDL_RenderSimulateVSync(SDL_Renderer *renderer)
{ {
Uint32 now, elapsed; Uint64 now, elapsed;
const Uint32 interval = renderer->simulate_vsync_interval; const Uint64 interval = renderer->simulate_vsync_interval_ns;
if (!interval) { if (!interval) {
/* We can't do sub-ms delay, so just return here */ /* We can't do sub-ns delay, so just return here */
return; return;
} }
now = SDL_GetTicks(); now = SDL_GetTicksNS();
elapsed = (now - renderer->last_present); elapsed = (now - renderer->last_present);
if (elapsed < interval) { if (elapsed < interval) {
Uint32 duration = (interval - elapsed); Uint64 duration = (interval - elapsed);
SDL_Delay(duration); SDL_DelayNS(duration);
now = SDL_GetTicks(); now = SDL_GetTicksNS();
} }
elapsed = (now - renderer->last_present); elapsed = (now - renderer->last_present);
if (!renderer->last_present || elapsed > 1000) { if (!renderer->last_present || elapsed > SDL_NS_TO_MS(1000)) {
/* It's been too long, reset the presentation timeline */ /* It's been too long, reset the presentation timeline */
renderer->last_present = now; renderer->last_present = now;
} else { } else {

View File

@ -209,8 +209,8 @@ struct SDL_Renderer
/* Whether we should simulate vsync */ /* Whether we should simulate vsync */
SDL_bool wanted_vsync; SDL_bool wanted_vsync;
SDL_bool simulate_vsync; SDL_bool simulate_vsync;
Uint32 simulate_vsync_interval; Uint64 simulate_vsync_interval_ns;
Uint32 last_present; Uint64 last_present;
/* The logical resolution for rendering */ /* The logical resolution for rendering */
int logical_w; int logical_w;

View File

@ -481,4 +481,43 @@ void SDL_DetachThread(SDL_Thread *thread)
} }
} }
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeoutNS(sem, SDL_MUTEX_MAXWAIT);
}
int SDL_SemTryWait(SDL_sem *sem)
{
return SDL_SemWaitTimeoutNS(sem, 0);
}
int SDL_SemWaitTimeout(SDL_sem *sem, Sint32 timeoutMS)
{
Sint64 timeoutNS;
if (timeoutMS >= 0) {
timeoutNS = SDL_MS_TO_NS(timeoutMS);
} else {
timeoutNS = -1;
}
return SDL_SemWaitTimeoutNS(sem, timeoutNS);
}
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeoutNS(cond, mutex, SDL_MUTEX_MAXWAIT);
}
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Sint32 timeoutMS)
{
Sint64 timeoutNS;
if (timeoutMS >= 0) {
timeoutNS = SDL_MS_TO_NS(timeoutMS);
} else {
timeoutNS = -1;
}
return SDL_CondWaitTimeoutNS(cond, mutex, timeoutNS);
}
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -37,8 +37,7 @@
#define SDL_DestroyCond_generic SDL_DestroyCond #define SDL_DestroyCond_generic SDL_DestroyCond
#define SDL_CondSignal_generic SDL_CondSignal #define SDL_CondSignal_generic SDL_CondSignal
#define SDL_CondBroadcast_generic SDL_CondBroadcast #define SDL_CondBroadcast_generic SDL_CondBroadcast
#define SDL_CondWait_generic SDL_CondWait #define SDL_CondWaitTimeoutNS_generic SDL_CondWaitTimeoutNS
#define SDL_CondWaitTimeout_generic SDL_CondWaitTimeout
#endif #endif
typedef struct SDL_cond_generic typedef struct SDL_cond_generic
@ -148,7 +147,7 @@ int SDL_CondBroadcast_generic(SDL_cond *_cond)
return 0; return 0;
} }
/* Wait on the condition variable for at most 'ms' milliseconds. /* Wait on the condition variable for at most 'timeoutNS' nanoseconds.
The mutex must be locked before entering this function! The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait. The mutex is unlocked during the wait, and locked again after the wait.
@ -169,7 +168,7 @@ Thread B:
SDL_CondSignal(cond); SDL_CondSignal(cond);
SDL_UnlockMutex(lock); SDL_UnlockMutex(lock);
*/ */
int SDL_CondWaitTimeout_generic(SDL_cond *_cond, SDL_mutex *mutex, Uint32 ms) int SDL_CondWaitTimeoutNS_generic(SDL_cond *_cond, SDL_mutex *mutex, Sint64 timeoutNS)
{ {
SDL_cond_generic *cond = (SDL_cond_generic *)_cond; SDL_cond_generic *cond = (SDL_cond_generic *)_cond;
int retval; int retval;
@ -190,11 +189,7 @@ int SDL_CondWaitTimeout_generic(SDL_cond *_cond, SDL_mutex *mutex, Uint32 ms)
SDL_UnlockMutex(mutex); SDL_UnlockMutex(mutex);
/* Wait for a signal */ /* Wait for a signal */
if (ms == SDL_MUTEX_MAXWAIT) { retval = SDL_SemWaitTimeoutNS(cond->wait_sem, timeoutNS);
retval = SDL_SemWait(cond->wait_sem);
} else {
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
}
/* Let the signaler know we have completed the wait, otherwise /* Let the signaler know we have completed the wait, otherwise
the signaler can race ahead and get the condition semaphore the signaler can race ahead and get the condition semaphore
@ -223,10 +218,4 @@ int SDL_CondWaitTimeout_generic(SDL_cond *_cond, SDL_mutex *mutex, Uint32 ms)
return retval; return retval;
} }
/* Wait on the condition variable forever */
int SDL_CondWait_generic(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout_generic(cond, mutex, SDL_MUTEX_MAXWAIT);
}
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -29,9 +29,7 @@ SDL_cond *SDL_CreateCond_generic(void);
void SDL_DestroyCond_generic(SDL_cond *cond); void SDL_DestroyCond_generic(SDL_cond *cond);
int SDL_CondSignal_generic(SDL_cond *cond); int SDL_CondSignal_generic(SDL_cond *cond);
int SDL_CondBroadcast_generic(SDL_cond *cond); int SDL_CondBroadcast_generic(SDL_cond *cond);
int SDL_CondWait_generic(SDL_cond *cond, SDL_mutex *mutex); int SDL_CondWaitTimeoutNS_generic(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS);
int SDL_CondWaitTimeout_generic(SDL_cond *cond,
SDL_mutex *mutex, Uint32 ms);
#endif /* SDL_THREAD_GENERIC_COND_SUFFIX */ #endif /* SDL_THREAD_GENERIC_COND_SUFFIX */

View File

@ -37,17 +37,7 @@ void SDL_DestroySemaphore(SDL_sem *sem)
{ {
} }
int SDL_SemTryWait(SDL_sem *sem) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{
return SDL_SetError("SDL not built with thread support");
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
return SDL_SetError("SDL not built with thread support");
}
int SDL_SemWait(SDL_sem *sem)
{ {
return SDL_SetError("SDL not built with thread support"); return SDL_SetError("SDL not built with thread support");
} }
@ -117,7 +107,7 @@ void SDL_DestroySemaphore(SDL_sem *sem)
} }
} }
int SDL_SemTryWait(SDL_sem *sem) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{ {
int retval; int retval;
@ -125,6 +115,8 @@ int SDL_SemTryWait(SDL_sem *sem)
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
/* A timeout of 0 is an easy case */
if (timeoutNS == 0) {
retval = SDL_MUTEX_TIMEDOUT; retval = SDL_MUTEX_TIMEDOUT;
SDL_LockMutex(sem->count_lock); SDL_LockMutex(sem->count_lock);
if (sem->count > 0) { if (sem->count > 0) {
@ -134,27 +126,14 @@ int SDL_SemTryWait(SDL_sem *sem)
SDL_UnlockMutex(sem->count_lock); SDL_UnlockMutex(sem->count_lock);
return retval; return retval;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
int retval;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
/* A timeout of 0 is an easy case */
if (timeout == 0) {
return SDL_SemTryWait(sem);
} }
SDL_LockMutex(sem->count_lock); SDL_LockMutex(sem->count_lock);
++sem->waiters_count; ++sem->waiters_count;
retval = 0; retval = 0;
while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) { while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) {
retval = SDL_CondWaitTimeout(sem->count_nonzero, retval = SDL_CondWaitTimeoutNS(sem->count_nonzero,
sem->count_lock, timeout); sem->count_lock, timeoutNS);
} }
--sem->waiters_count; --sem->waiters_count;
if (retval == 0) { if (retval == 0) {
@ -165,11 +144,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return retval; return retval;
} }
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
Uint32 Uint32
SDL_SemValue(SDL_sem *sem) SDL_SemValue(SDL_sem *sem)
{ {
@ -201,4 +175,5 @@ int SDL_SemPost(SDL_sem *sem)
} }
#endif /* SDL_THREADS_DISABLED */ #endif /* SDL_THREADS_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -74,7 +74,7 @@ int SDL_CondBroadcast(SDL_cond *cond)
return 0; return 0;
} }
/* Wait on the condition variable for at most 'ms' milliseconds. /* Wait on the condition variable for at most 'timeoutNS' nanoseconds.
The mutex must be locked before entering this function! The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait. The mutex is unlocked during the wait, and locked again after the wait.
@ -95,7 +95,7 @@ Thread B:
SDL_CondSignal(cond); SDL_CondSignal(cond);
SDL_UnlockMutex(lock); SDL_UnlockMutex(lock);
*/ */
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) int SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
{ {
Result res; Result res;
@ -107,22 +107,15 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
} }
res = 0; res = 0;
if (ms == SDL_MUTEX_MAXWAIT) { if (timeoutNS < 0) {
CondVar_Wait(&cond->cond_variable, &mutex->lock.lock); CondVar_Wait(&cond->cond_variable, &mutex->lock.lock);
} else { } else {
res = CondVar_WaitTimeout(&cond->cond_variable, &mutex->lock.lock, res = CondVar_WaitTimeout(&cond->cond_variable, &mutex->lock.lock, timeoutNS);
(s64)ms * 1000000LL);
} }
return R_SUCCEEDED(res) ? 0 : SDL_MUTEX_TIMEDOUT; return R_SUCCEEDED(res) ? 0 : SDL_MUTEX_TIMEDOUT;
} }
/* Wait on the condition variable forever */
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
#endif /* SDL_THREAD_N3DS */ #endif /* SDL_THREAD_N3DS */
/* vi: set sts=4 ts=4 sw=4 expandtab: */ /* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@ -62,16 +62,7 @@ void SDL_DestroySemaphore(SDL_sem *sem)
} }
} }
int SDL_SemTryWait(SDL_sem *sem) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
return SDL_SemWaitTimeout(sem, 0);
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{ {
int retval; int retval;
@ -79,12 +70,15 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
if (timeout == SDL_MUTEX_MAXWAIT) { if (timeoutNS == SDL_MUTEX_MAXWAIT) {
LightSemaphore_Acquire(&sem->semaphore, 1); LightSemaphore_Acquire(&sem->semaphore, 1);
retval = 0; retval = 0;
} else { } else {
int return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1); int return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1);
if (return_code != 0) { if (return_code != 0) {
/* FIXME: Does this code guarantee a wall clock timeout here?
* Can we handle sub-millisecond delays? */
u32 timeout = (u32)SDL_NS_TO_MS(timeoutNS);
for (u32 i = 0; i < timeout; i++) { for (u32 i = 0; i < timeout; i++) {
svcSleepThread(1000000LL); svcSleepThread(1000000LL);
return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1); return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1);
@ -99,11 +93,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return retval; return retval;
} }
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
Uint32 Uint32
SDL_SemValue(SDL_sem *sem) SDL_SemValue(SDL_sem *sem)
{ {

View File

@ -100,19 +100,27 @@ void SDL_DestroySemaphore(SDL_sem *sem)
} }
} }
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{ {
if (sem == NULL) { if (sem == NULL) {
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
if (timeout == SDL_MUTEX_MAXWAIT) { if (timeoutNS == 0) {
if (sem->count > 0) {
--sem->count;
return 0;
}
return SDL_MUTEX_TIMEOUT;
}
if (timeoutNS == SDL_MUTEX_MAXWAIT) {
WaitAll(sem); WaitAll(sem);
return SDL_MUTEX_MAXWAIT; return 0;
} }
RThread thread; RThread thread;
TInfo *info = new (ELeave) TInfo(timeout, sem->handle); TInfo *info = new (ELeave) TInfo((TInt)SDL_NS_TO_MS(timeoutNS), sem->handle);
TInt status = CreateUnique(NewThread, &thread, info); TInt status = CreateUnique(NewThread, &thread, info);
if (status != KErrNone) { if (status != KErrNone) {
@ -130,23 +138,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return info->iVal; return info->iVal;
} }
int SDL_SemTryWait(SDL_sem *sem)
{
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
if (sem->count > 0) {
sem->count--;
}
return SDL_MUTEX_TIMEOUT;
}
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
Uint32 Uint32
SDL_SemValue(SDL_sem *sem) SDL_SemValue(SDL_sem *sem)
{ {

View File

@ -79,7 +79,7 @@ void SDL_DestroySemaphore(SDL_sem *sem)
} }
} }
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{ {
int ret; int ret;
struct timer_alarm_t alarm; struct timer_alarm_t alarm;
@ -89,15 +89,15 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
if (timeout == 0) { if (timeoutNS == 0) {
if (PollSema(sem->semid) < 0) { if (PollSema(sem->semid) < 0) {
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
} }
return 0; return 0;
} }
if (timeout != SDL_MUTEX_MAXWAIT) { if (timeoutNS != SDL_MUTEX_MAXWAIT) {
SetTimerAlarm(&alarm, MSec2TimerBusClock(timeout), &usercb, (void *)GetThreadId()); SetTimerAlarm(&alarm, MSec2TimerBusClock(SDL_NS_TO_MS(timeoutNS)), &usercb, (void *)GetThreadId());
} }
ret = WaitSema(sem->semid); ret = WaitSema(sem->semid);
@ -109,16 +109,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return 0; // Wait condition satisfied. return 0; // Wait condition satisfied.
} }
int SDL_SemTryWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, 0);
}
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
/* Returns the current count of the semaphore */ /* Returns the current count of the semaphore */
Uint32 SDL_SemValue(SDL_sem *sem) Uint32 SDL_SemValue(SDL_sem *sem)
{ {

View File

@ -132,7 +132,7 @@ int SDL_CondBroadcast(SDL_cond *cond)
return 0; return 0;
} }
/* Wait on the condition variable for at most 'ms' milliseconds. /* Wait on the condition variable for at most 'timeoutNS' nanoseconds.
The mutex must be locked before entering this function! The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait. The mutex is unlocked during the wait, and locked again after the wait.
@ -153,7 +153,7 @@ Thread B:
SDL_CondSignal(cond); SDL_CondSignal(cond);
SDL_UnlockMutex(lock); SDL_UnlockMutex(lock);
*/ */
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) int SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
{ {
int retval; int retval;
@ -173,11 +173,7 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
SDL_UnlockMutex(mutex); SDL_UnlockMutex(mutex);
/* Wait for a signal */ /* Wait for a signal */
if (ms == SDL_MUTEX_MAXWAIT) { retval = SDL_SemWaitTimeout(cond->wait_sem, timeoutNS);
retval = SDL_SemWait(cond->wait_sem);
} else {
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
}
/* Let the signaler know we have completed the wait, otherwise /* Let the signaler know we have completed the wait, otherwise
the signaler can race ahead and get the condition semaphore the signaler can race ahead and get the condition semaphore
@ -206,12 +202,6 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
return retval; return retval;
} }
/* Wait on the condition variable forever */
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
#endif /* SDL_THREAD_PSP */ #endif /* SDL_THREAD_PSP */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -73,16 +73,17 @@ void SDL_DestroySemaphore(SDL_sem *sem)
* If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass * If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass
* NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout
* is specified, convert it to microseconds. */ * is specified, convert it to microseconds. */
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{ {
Uint32 *pTimeout; SceUInt timeoutUS;
SceUInt *pTimeout;
int res; int res;
if (sem == NULL) { if (sem == NULL) {
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
if (timeout == 0) { if (timeoutNS == 0) {
res = sceKernelPollSema(sem->semid, 1); res = sceKernelPollSema(sem->semid, 1);
if (res < 0) { if (res < 0) {
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
@ -90,14 +91,14 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return 0; return 0;
} }
if (timeout == SDL_MUTEX_MAXWAIT) { if (timeoutNS < 0) {
pTimeout = NULL; pTimeout = NULL;
} else { } else {
timeout *= 1000; /* Convert to microseconds. */ timeoutUS = (SceUInt)SDL_NS_TO_US(timeoutNS); /* Convert to microseconds. */
pTimeout = &timeout; pTimeout = &timeoutUS;
} }
res = sceKernelWaitSema(sem->semid, 1, (SceUInt *)pTimeout); res = sceKernelWaitSema(sem->semid, 1, pTimeout);
switch (res) { switch (res) {
case SCE_KERNEL_ERROR_OK: case SCE_KERNEL_ERROR_OK:
return 0; return 0;
@ -108,16 +109,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
} }
} }
int SDL_SemTryWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, 0);
}
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
/* Returns the current count of the semaphore */ /* Returns the current count of the semaphore */
Uint32 SDL_SemValue(SDL_sem *sem) Uint32 SDL_SemValue(SDL_sem *sem)
{ {

View File

@ -91,7 +91,7 @@ int SDL_CondBroadcast(SDL_cond *cond)
return retval; return retval;
} }
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) int SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
{ {
int retval; int retval;
#ifndef HAVE_CLOCK_GETTIME #ifndef HAVE_CLOCK_GETTIME
@ -103,18 +103,25 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
return SDL_InvalidParamError("cond"); return SDL_InvalidParamError("cond");
} }
if (timeoutNS < 0) {
if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
return SDL_SetError("pthread_cond_wait() failed");
}
return 0;
}
#ifdef HAVE_CLOCK_GETTIME #ifdef HAVE_CLOCK_GETTIME
clock_gettime(CLOCK_REALTIME, &abstime); clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_nsec += (ms % 1000) * 1000000; abstime.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
abstime.tv_sec += ms / 1000; abstime.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
#else #else
gettimeofday(&delta, NULL); gettimeofday(&delta, NULL);
abstime.tv_sec = delta.tv_sec + (ms / 1000); abstime.tv_sec = delta.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
abstime.tv_nsec = (long)(delta.tv_usec + (ms % 1000) * 1000) * 1000; abstime.tv_nsec = SDL_US_TO_NS(delta.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
#endif #endif
if (abstime.tv_nsec > 1000000000) { while (abstime.tv_nsec > 1000000000) {
abstime.tv_sec += 1; abstime.tv_sec += 1;
abstime.tv_nsec -= 1000000000; abstime.tv_nsec -= 1000000000;
} }
@ -136,17 +143,4 @@ tryagain:
return retval; return retval;
} }
/* Wait on the condition variable, unlocking the provided mutex.
The mutex must be locked before entering this function!
*/
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
if (cond == NULL) {
return SDL_InvalidParamError("cond");
} else if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
return SDL_SetError("pthread_cond_wait() failed");
}
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -63,39 +63,7 @@ void SDL_DestroySemaphore(SDL_sem *sem)
} }
} }
int SDL_SemTryWait(SDL_sem *sem) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{
int retval;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
retval = SDL_MUTEX_TIMEDOUT;
if (sem_trywait(&sem->sem) == 0) {
retval = 0;
}
return retval;
}
int SDL_SemWait(SDL_sem *sem)
{
int retval;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
do {
retval = sem_wait(&sem->sem);
} while (retval < 0 && errno == EINTR);
if (retval < 0) {
retval = SDL_SetError("sem_wait() failed");
}
return retval;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{ {
int retval; int retval;
#ifdef HAVE_SEM_TIMEDWAIT #ifdef HAVE_SEM_TIMEDWAIT
@ -104,7 +72,7 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
#endif #endif
struct timespec ts_timeout; struct timespec ts_timeout;
#else #else
Uint32 end; Uint64 end;
#endif #endif
if (sem == NULL) { if (sem == NULL) {
@ -112,11 +80,22 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
} }
/* Try the easy cases first */ /* Try the easy cases first */
if (timeout == 0) { if (timeoutNS == 0) {
return SDL_SemTryWait(sem); retval = SDL_MUTEX_TIMEDOUT;
if (sem_trywait(&sem->sem) == 0) {
retval = 0;
} }
if (timeout == SDL_MUTEX_MAXWAIT) { return retval;
return SDL_SemWait(sem); }
if (timeoutNS < 0) {
do {
retval = sem_wait(&sem->sem);
} while (retval < 0 && errno == EINTR);
if (retval < 0) {
retval = SDL_SetError("sem_wait() failed");
}
return retval;
} }
#ifdef HAVE_SEM_TIMEDWAIT #ifdef HAVE_SEM_TIMEDWAIT
@ -128,18 +107,18 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
clock_gettime(CLOCK_REALTIME, &ts_timeout); clock_gettime(CLOCK_REALTIME, &ts_timeout);
/* Add our timeout to current time */ /* Add our timeout to current time */
ts_timeout.tv_nsec += (timeout % 1000) * 1000000; ts_timeout.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
ts_timeout.tv_sec += timeout / 1000; ts_timeout.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
#else #else
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
/* Add our timeout to current time */ /* Add our timeout to current time */
ts_timeout.tv_sec = now.tv_sec + (timeout / 1000); ts_timeout.tv_sec = now.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000; ts_timeout.tv_nsec = SDL_US_TO_NS(now.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
#endif #endif
/* Wrap the second if needed */ /* Wrap the second if needed */
if (ts_timeout.tv_nsec > 1000000000) { while (ts_timeout.tv_nsec > 1000000000) {
ts_timeout.tv_sec += 1; ts_timeout.tv_sec += 1;
ts_timeout.tv_nsec -= 1000000000; ts_timeout.tv_nsec -= 1000000000;
} }
@ -157,12 +136,13 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
} }
} }
#else #else
end = SDL_GetTicks() + timeout; end = SDL_GetTicksNS() + timeoutNS;
while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) { while (sem_trywait(&sem->sem) != 0) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) { if (SDL_GetTicksNS() >= end) {
retval = SDL_MUTEX_TIMEDOUT;
break; break;
} }
SDL_Delay(1); SDL_DelayNS(100);
} }
#endif /* HAVE_SEM_TIMEDWAIT */ #endif /* HAVE_SEM_TIMEDWAIT */

View File

@ -85,7 +85,7 @@ SDL_CondBroadcast(SDL_cond *cond)
return 0; return 0;
} }
/* Wait on the condition variable for at most 'ms' milliseconds. /* Wait on the condition variable for at most 'timeoutNS' nanoseconds.
The mutex must be locked before entering this function! The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait. The mutex is unlocked during the wait, and locked again after the wait.
@ -107,7 +107,7 @@ Thread B:
SDL_UnlockMutex(lock); SDL_UnlockMutex(lock);
*/ */
extern "C" int extern "C" int
SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
{ {
if (cond == NULL) { if (cond == NULL) {
return SDL_InvalidParamError("cond"); return SDL_InvalidParamError("cond");
@ -119,7 +119,7 @@ SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
try { try {
std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::adopt_lock_t()); std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::adopt_lock_t());
if (ms == SDL_MUTEX_MAXWAIT) { if (timeoutNS < 0) {
cond->cpp_cond.wait( cond->cpp_cond.wait(
cpp_lock); cpp_lock);
cpp_lock.release(); cpp_lock.release();
@ -127,7 +127,7 @@ SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
} else { } else {
auto wait_result = cond->cpp_cond.wait_for( auto wait_result = cond->cpp_cond.wait_for(
cpp_lock, cpp_lock,
std::chrono::duration<Uint32, std::milli>(ms)); std::chrono::duration<Sint64, std::nano>(timeoutNS));
cpp_lock.release(); cpp_lock.release();
if (wait_result == std::cv_status::timeout) { if (wait_result == std::cv_status::timeout) {
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
@ -136,15 +136,8 @@ SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
} }
} }
} catch (std::system_error &ex) { } catch (std::system_error &ex) {
return SDL_SetError("unable to wait on a C++ condition variable: code=%d; %s", ex.code(), ex.what()); return SDL_SetError("Unable to wait on a C++ condition variable: code=%d; %s", ex.code(), ex.what());
} }
} }
/* Wait on the condition variable forever */
extern "C" int
SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -132,7 +132,7 @@ int SDL_CondBroadcast(SDL_cond *cond)
return 0; return 0;
} }
/* Wait on the condition variable for at most 'ms' milliseconds. /* Wait on the condition variable for at most 'timeoutNS' nanoseconds.
The mutex must be locked before entering this function! The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait. The mutex is unlocked during the wait, and locked again after the wait.
@ -153,7 +153,7 @@ Thread B:
SDL_CondSignal(cond); SDL_CondSignal(cond);
SDL_UnlockMutex(lock); SDL_UnlockMutex(lock);
*/ */
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) int SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
{ {
int retval; int retval;
@ -173,11 +173,7 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
SDL_UnlockMutex(mutex); SDL_UnlockMutex(mutex);
/* Wait for a signal */ /* Wait for a signal */
if (ms == SDL_MUTEX_MAXWAIT) { retval = SDL_SemWaitTimeoutNS(cond->wait_sem, timeoutNS);
retval = SDL_SemWait(cond->wait_sem);
} else {
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
}
/* Let the signaler know we have completed the wait, otherwise /* Let the signaler know we have completed the wait, otherwise
the signaler can race ahead and get the condition semaphore the signaler can race ahead and get the condition semaphore
@ -206,12 +202,6 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
return retval; return retval;
} }
/* Wait on the condition variable forever */
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
#endif /* SDL_THREAD_VITA */ #endif /* SDL_THREAD_VITA */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -74,16 +74,17 @@ void SDL_DestroySemaphore(SDL_sem *sem)
* If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass * If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass
* NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout
* is specified, convert it to microseconds. */ * is specified, convert it to microseconds. */
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{ {
Uint32 *pTimeout; SceUInt timeoutUS;
SceUInt *pTimeout;
int res; int res;
if (sem == NULL) { if (sem == NULL) {
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
if (timeout == 0) { if (timeoutNS == 0) {
res = sceKernelPollSema(sem->semid, 1); res = sceKernelPollSema(sem->semid, 1);
if (res < 0) { if (res < 0) {
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
@ -91,11 +92,11 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return 0; return 0;
} }
if (timeout == SDL_MUTEX_MAXWAIT) { if (timeoutNS < 0) {
pTimeout = NULL; pTimeout = NULL;
} else { } else {
timeout *= 1000; /* Convert to microseconds. */ timeoutUS = (SceUInt)SDL_NS_TO_US(timeoutNS); /* Convert to microseconds. */
pTimeout = &timeout; pTimeout = &timeoutUS;
} }
res = sceKernelWaitSema(sem->semid, 1, pTimeout); res = sceKernelWaitSema(sem->semid, 1, pTimeout);
@ -105,20 +106,10 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
case SCE_KERNEL_ERROR_WAIT_TIMEOUT: case SCE_KERNEL_ERROR_WAIT_TIMEOUT:
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
default: default:
return SDL_SetError("WaitForSingleObject() failed"); return SDL_SetError("sceKernelWaitSema() failed");
} }
} }
int SDL_SemTryWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, 0);
}
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
/* Returns the current count of the semaphore */ /* Returns the current count of the semaphore */
Uint32 SDL_SemValue(SDL_sem *sem) Uint32 SDL_SemValue(SDL_sem *sem)
{ {

View File

@ -27,8 +27,7 @@ typedef SDL_cond *(*pfnSDL_CreateCond)(void);
typedef void (*pfnSDL_DestroyCond)(SDL_cond *); typedef void (*pfnSDL_DestroyCond)(SDL_cond *);
typedef int (*pfnSDL_CondSignal)(SDL_cond *); typedef int (*pfnSDL_CondSignal)(SDL_cond *);
typedef int (*pfnSDL_CondBroadcast)(SDL_cond *); typedef int (*pfnSDL_CondBroadcast)(SDL_cond *);
typedef int (*pfnSDL_CondWait)(SDL_cond *, SDL_mutex *); typedef int (*pfnSDL_CondWaitTimeoutNS)(SDL_cond *, SDL_mutex *, Sint64);
typedef int (*pfnSDL_CondWaitTimeout)(SDL_cond *, SDL_mutex *, Uint32);
typedef struct SDL_cond_impl_t typedef struct SDL_cond_impl_t
{ {
@ -36,8 +35,7 @@ typedef struct SDL_cond_impl_t
pfnSDL_DestroyCond Destroy; pfnSDL_DestroyCond Destroy;
pfnSDL_CondSignal Signal; pfnSDL_CondSignal Signal;
pfnSDL_CondBroadcast Broadcast; pfnSDL_CondBroadcast Broadcast;
pfnSDL_CondWait Wait; pfnSDL_CondWaitTimeoutNS WaitTimeoutNS;
pfnSDL_CondWaitTimeout WaitTimeout;
} SDL_cond_impl_t; } SDL_cond_impl_t;
/* Implementation will be chosen at runtime based on available Kernel features */ /* Implementation will be chosen at runtime based on available Kernel features */
@ -125,7 +123,7 @@ static int SDL_CondBroadcast_cv(SDL_cond *_cond)
return 0; return 0;
} }
static int SDL_CondWaitTimeout_cv(SDL_cond *_cond, SDL_mutex *_mutex, Uint32 ms) static int SDL_CondWaitTimeoutNS_cv(SDL_cond *_cond, SDL_mutex *_mutex, Sint64 timeoutNS)
{ {
SDL_cond_cv *cond = (SDL_cond_cv *)_cond; SDL_cond_cv *cond = (SDL_cond_cv *)_cond;
DWORD timeout; DWORD timeout;
@ -138,10 +136,10 @@ static int SDL_CondWaitTimeout_cv(SDL_cond *_cond, SDL_mutex *_mutex, Uint32 ms)
return SDL_InvalidParamError("mutex"); return SDL_InvalidParamError("mutex");
} }
if (ms == SDL_MUTEX_MAXWAIT) { if (timeoutNS < 0) {
timeout = INFINITE; timeout = INFINITE;
} else { } else {
timeout = (DWORD)ms; timeout = (DWORD)SDL_NS_TO_MS(timeoutNS);
} }
if (SDL_mutex_impl_active.Type == SDL_MUTEX_SRW) { if (SDL_mutex_impl_active.Type == SDL_MUTEX_SRW) {
@ -188,18 +186,12 @@ static int SDL_CondWaitTimeout_cv(SDL_cond *_cond, SDL_mutex *_mutex, Uint32 ms)
return ret; return ret;
} }
static int SDL_CondWait_cv(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout_cv(cond, mutex, SDL_MUTEX_MAXWAIT);
}
static const SDL_cond_impl_t SDL_cond_impl_cv = { static const SDL_cond_impl_t SDL_cond_impl_cv = {
&SDL_CreateCond_cv, &SDL_CreateCond_cv,
&SDL_DestroyCond_cv, &SDL_DestroyCond_cv,
&SDL_CondSignal_cv, &SDL_CondSignal_cv,
&SDL_CondBroadcast_cv, &SDL_CondBroadcast_cv,
&SDL_CondWait_cv, &SDL_CondWaitTimeoutNS_cv,
&SDL_CondWaitTimeout_cv,
}; };
/** /**
@ -211,8 +203,7 @@ static const SDL_cond_impl_t SDL_cond_impl_generic = {
&SDL_DestroyCond_generic, &SDL_DestroyCond_generic,
&SDL_CondSignal_generic, &SDL_CondSignal_generic,
&SDL_CondBroadcast_generic, &SDL_CondBroadcast_generic,
&SDL_CondWait_generic, &SDL_CondWaitTimeoutNS_generic,
&SDL_CondWaitTimeout_generic,
}; };
SDL_cond * SDL_cond *
@ -272,14 +263,9 @@ int SDL_CondBroadcast(SDL_cond *cond)
return SDL_cond_impl_active.Broadcast(cond); return SDL_cond_impl_active.Broadcast(cond);
} }
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) int SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
{ {
return SDL_cond_impl_active.WaitTimeout(cond, mutex, ms); return SDL_cond_impl_active.WaitTimeoutNS(cond, mutex, timeoutNS);
}
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_cond_impl_active.Wait(cond, mutex);
} }
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -37,9 +37,7 @@
typedef SDL_sem *(*pfnSDL_CreateSemaphore)(Uint32); typedef SDL_sem *(*pfnSDL_CreateSemaphore)(Uint32);
typedef void (*pfnSDL_DestroySemaphore)(SDL_sem *); typedef void (*pfnSDL_DestroySemaphore)(SDL_sem *);
typedef int (*pfnSDL_SemWaitTimeout)(SDL_sem *, Uint32); typedef int (*pfnSDL_SemWaitTimeoutNS)(SDL_sem *, Sint64);
typedef int (*pfnSDL_SemTryWait)(SDL_sem *);
typedef int (*pfnSDL_SemWait)(SDL_sem *);
typedef Uint32 (*pfnSDL_SemValue)(SDL_sem *); typedef Uint32 (*pfnSDL_SemValue)(SDL_sem *);
typedef int (*pfnSDL_SemPost)(SDL_sem *); typedef int (*pfnSDL_SemPost)(SDL_sem *);
@ -47,9 +45,7 @@ typedef struct SDL_semaphore_impl_t
{ {
pfnSDL_CreateSemaphore Create; pfnSDL_CreateSemaphore Create;
pfnSDL_DestroySemaphore Destroy; pfnSDL_DestroySemaphore Destroy;
pfnSDL_SemWaitTimeout WaitTimeout; pfnSDL_SemWaitTimeoutNS WaitTimeoutNS;
pfnSDL_SemTryWait TryWait;
pfnSDL_SemWait Wait;
pfnSDL_SemValue Value; pfnSDL_SemValue Value;
pfnSDL_SemPost Post; pfnSDL_SemPost Post;
} SDL_sem_impl_t; } SDL_sem_impl_t;
@ -108,15 +104,19 @@ static void SDL_DestroySemaphore_atom(SDL_sem *sem)
} }
} }
static int SDL_SemTryWait_atom(SDL_sem *_sem) static int SDL_SemWaitTimeoutNS_atom(SDL_sem *_sem, Sint64 timeoutNS)
{ {
SDL_sem_atom *sem = (SDL_sem_atom *)_sem; SDL_sem_atom *sem = (SDL_sem_atom *)_sem;
LONG count; LONG count;
Uint64 now;
Uint64 deadline;
DWORD timeout_eff;
if (sem == NULL) { if (sem == NULL) {
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
if (timeoutNS == 0) {
count = sem->count; count = sem->count;
if (count == 0) { if (count == 0) {
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
@ -127,17 +127,8 @@ static int SDL_SemTryWait_atom(SDL_sem *_sem)
} }
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
}
static int SDL_SemWait_atom(SDL_sem *_sem)
{
SDL_sem_atom *sem = (SDL_sem_atom *)_sem;
LONG count;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
} }
if (timeoutNS < 0) {
for (;;) { for (;;) {
count = sem->count; count = sem->count;
while (count == 0) { while (count == 0) {
@ -151,38 +142,22 @@ static int SDL_SemWait_atom(SDL_sem *_sem)
return 0; return 0;
} }
} }
}
static int SDL_SemWaitTimeout_atom(SDL_sem *_sem, Uint32 timeout)
{
SDL_sem_atom *sem = (SDL_sem_atom *)_sem;
LONG count;
Uint32 now;
Uint32 deadline;
DWORD timeout_eff;
if (timeout == SDL_MUTEX_MAXWAIT) {
return SDL_SemWait_atom(_sem);
}
if (sem == NULL) {
return SDL_InvalidParamError("sem");
} }
/** /**
* WaitOnAddress is subject to spurious and stolen wakeups so we * WaitOnAddress is subject to spurious and stolen wakeups so we
* need to recalculate the effective timeout before every wait * need to recalculate the effective timeout before every wait
*/ */
now = SDL_GetTicks(); now = SDL_GetTicksNS();
deadline = now + (DWORD)timeout; deadline = now + timeoutNS;
for (;;) { for (;;) {
count = sem->count; count = sem->count;
/* If no semaphore is available we need to wait */ /* If no semaphore is available we need to wait */
while (count == 0) { while (count == 0) {
now = SDL_GetTicks(); now = SDL_GetTicksNS();
if (deadline > now) { if (deadline > now) {
timeout_eff = deadline - now; timeout_eff = (DWORD)SDL_NS_TO_MS(deadline - now);
} else { } else {
return SDL_MUTEX_TIMEDOUT; return SDL_MUTEX_TIMEDOUT;
} }
@ -232,9 +207,7 @@ static int SDL_SemPost_atom(SDL_sem *_sem)
static const SDL_sem_impl_t SDL_sem_impl_atom = { static const SDL_sem_impl_t SDL_sem_impl_atom = {
&SDL_CreateSemaphore_atom, &SDL_CreateSemaphore_atom,
&SDL_DestroySemaphore_atom, &SDL_DestroySemaphore_atom,
&SDL_SemWaitTimeout_atom, &SDL_SemWaitTimeoutNS_atom,
&SDL_SemTryWait_atom,
&SDL_SemWait_atom,
&SDL_SemValue_atom, &SDL_SemValue_atom,
&SDL_SemPost_atom, &SDL_SemPost_atom,
}; };
@ -289,7 +262,7 @@ static void SDL_DestroySemaphore_kern(SDL_sem *_sem)
} }
} }
static int SDL_SemWaitTimeout_kern(SDL_sem *_sem, Uint32 timeout) static int SDL_SemWaitTimeoutNS_kern(SDL_sem *_sem, Sint64 timeoutNS)
{ {
SDL_sem_kern *sem = (SDL_sem_kern *)_sem; SDL_sem_kern *sem = (SDL_sem_kern *)_sem;
int retval; int retval;
@ -299,10 +272,10 @@ static int SDL_SemWaitTimeout_kern(SDL_sem *_sem, Uint32 timeout)
return SDL_InvalidParamError("sem"); return SDL_InvalidParamError("sem");
} }
if (timeout == SDL_MUTEX_MAXWAIT) { if (timeoutNS < 0) {
dwMilliseconds = INFINITE; dwMilliseconds = INFINITE;
} else { } else {
dwMilliseconds = (DWORD)timeout; dwMilliseconds = (DWORD)SDL_NS_TO_MS(timeoutNS);
} }
switch (WaitForSingleObjectEx(sem->id, dwMilliseconds, FALSE)) { switch (WaitForSingleObjectEx(sem->id, dwMilliseconds, FALSE)) {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
@ -319,16 +292,6 @@ static int SDL_SemWaitTimeout_kern(SDL_sem *_sem, Uint32 timeout)
return retval; return retval;
} }
static int SDL_SemTryWait_kern(SDL_sem *sem)
{
return SDL_SemWaitTimeout_kern(sem, 0);
}
static int SDL_SemWait_kern(SDL_sem *sem)
{
return SDL_SemWaitTimeout_kern(sem, SDL_MUTEX_MAXWAIT);
}
/* Returns the current count of the semaphore */ /* Returns the current count of the semaphore */
static Uint32 SDL_SemValue_kern(SDL_sem *_sem) static Uint32 SDL_SemValue_kern(SDL_sem *_sem)
{ {
@ -362,9 +325,7 @@ static int SDL_SemPost_kern(SDL_sem *_sem)
static const SDL_sem_impl_t SDL_sem_impl_kern = { static const SDL_sem_impl_t SDL_sem_impl_kern = {
&SDL_CreateSemaphore_kern, &SDL_CreateSemaphore_kern,
&SDL_DestroySemaphore_kern, &SDL_DestroySemaphore_kern,
&SDL_SemWaitTimeout_kern, &SDL_SemWaitTimeoutNS_kern,
&SDL_SemTryWait_kern,
&SDL_SemWait_kern,
&SDL_SemValue_kern, &SDL_SemValue_kern,
&SDL_SemPost_kern, &SDL_SemPost_kern,
}; };
@ -417,19 +378,9 @@ void SDL_DestroySemaphore(SDL_sem *sem)
SDL_sem_impl_active.Destroy(sem); SDL_sem_impl_active.Destroy(sem);
} }
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{ {
return SDL_sem_impl_active.WaitTimeout(sem, timeout); return SDL_sem_impl_active.WaitTimeoutNS(sem, timeoutNS);
}
int SDL_SemTryWait(SDL_sem *sem)
{
return SDL_sem_impl_active.TryWait(sem);
}
int SDL_SemWait(SDL_sem *sem)
{
return SDL_sem_impl_active.Wait(sem);
} }
Uint32 Uint32

View File

@ -32,8 +32,8 @@ typedef struct _SDL_Timer
int timerID; int timerID;
SDL_TimerCallback callback; SDL_TimerCallback callback;
void *param; void *param;
Uint32 interval; Uint64 interval;
Uint32 scheduled; Uint64 scheduled;
SDL_atomic_t canceled; SDL_atomic_t canceled;
struct _SDL_Timer *next; struct _SDL_Timer *next;
} SDL_Timer; } SDL_Timer;
@ -82,7 +82,7 @@ static void SDL_AddTimerInternal(SDL_TimerData *data, SDL_Timer *timer)
prev = NULL; prev = NULL;
for (curr = data->timers; curr; prev = curr, curr = curr->next) { for (curr = data->timers; curr; prev = curr, curr = curr->next) {
if ((Sint32)(timer->scheduled - curr->scheduled) < 0) { if (curr->scheduled > timer->scheduled) {
break; break;
} }
} }
@ -103,7 +103,7 @@ static int SDLCALL SDL_TimerThread(void *_data)
SDL_Timer *current; SDL_Timer *current;
SDL_Timer *freelist_head = NULL; SDL_Timer *freelist_head = NULL;
SDL_Timer *freelist_tail = NULL; SDL_Timer *freelist_tail = NULL;
Uint32 tick, now, interval, delay; Uint64 tick, now, interval, delay;
/* Threaded timer loop: /* Threaded timer loop:
* 1. Queue timers added by other threads * 1. Queue timers added by other threads
@ -143,13 +143,13 @@ static int SDLCALL SDL_TimerThread(void *_data)
/* Initial delay if there are no timers */ /* Initial delay if there are no timers */
delay = SDL_MUTEX_MAXWAIT; delay = SDL_MUTEX_MAXWAIT;
tick = SDL_GetTicks(); tick = SDL_GetTicksNS();
/* Process all the pending timers for this tick */ /* Process all the pending timers for this tick */
while (data->timers) { while (data->timers) {
current = data->timers; current = data->timers;
if ((Sint32)(tick - current->scheduled) < 0) { if (tick < current->scheduled) {
/* Scheduled for the future, wait a bit */ /* Scheduled for the future, wait a bit */
delay = (current->scheduled - tick); delay = (current->scheduled - tick);
break; break;
@ -161,7 +161,8 @@ static int SDLCALL SDL_TimerThread(void *_data)
if (SDL_AtomicGet(&current->canceled)) { if (SDL_AtomicGet(&current->canceled)) {
interval = 0; interval = 0;
} else { } else {
interval = current->callback(current->interval, current->param); /* FIXME: We could potentially support sub-millisecond timers now */
interval = SDL_MS_TO_NS(current->callback((Uint32)SDL_NS_TO_MS(current->interval), current->param));
} }
if (interval > 0) { if (interval > 0) {
@ -183,7 +184,7 @@ static int SDLCALL SDL_TimerThread(void *_data)
} }
/* Adjust the delay based on processing time */ /* Adjust the delay based on processing time */
now = SDL_GetTicks(); now = SDL_GetTicksNS();
interval = (now - tick); interval = (now - tick);
if (interval > delay) { if (interval > delay) {
delay = 0; delay = 0;
@ -196,7 +197,7 @@ static int SDLCALL SDL_TimerThread(void *_data)
That's okay, it just means we run through the loop a few That's okay, it just means we run through the loop a few
extra times. extra times.
*/ */
SDL_SemWaitTimeout(data->sem, delay); SDL_SemWaitTimeoutNS(data->sem, delay);
} }
return 0; return 0;
} }
@ -271,8 +272,7 @@ void SDL_TimerQuit(void)
} }
} }
SDL_TimerID SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
{ {
SDL_TimerData *data = &SDL_timer_data; SDL_TimerData *data = &SDL_timer_data;
SDL_Timer *timer; SDL_Timer *timer;
@ -304,8 +304,8 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
timer->timerID = SDL_AtomicIncRef(&data->nextID); timer->timerID = SDL_AtomicIncRef(&data->nextID);
timer->callback = callback; timer->callback = callback;
timer->param = param; timer->param = param;
timer->interval = interval; timer->interval = SDL_MS_TO_NS(interval);
timer->scheduled = SDL_GetTicks() + interval; timer->scheduled = SDL_GetTicksNS() + timer->interval;
SDL_AtomicSet(&timer->canceled, 0); SDL_AtomicSet(&timer->canceled, 0);
entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry));
@ -334,8 +334,7 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
return entry->timerID; return entry->timerID;
} }
SDL_bool SDL_bool SDL_RemoveTimer(SDL_TimerID id)
SDL_RemoveTimer(SDL_TimerID id)
{ {
SDL_TimerData *data = &SDL_timer_data; SDL_TimerData *data = &SDL_timer_data;
SDL_TimerMap *prev, *entry; SDL_TimerMap *prev, *entry;
@ -417,8 +416,7 @@ void SDL_TimerQuit(void)
} }
} }
SDL_TimerID SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
{ {
SDL_TimerData *data = &SDL_timer_data; SDL_TimerData *data = &SDL_timer_data;
SDL_TimerMap *entry; SDL_TimerMap *entry;
@ -443,8 +441,7 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
return entry->timerID; return entry->timerID;
} }
SDL_bool SDL_bool SDL_RemoveTimer(SDL_TimerID id)
SDL_RemoveTimer(SDL_TimerID id)
{ {
SDL_TimerData *data = &SDL_timer_data; SDL_TimerData *data = &SDL_timer_data;
SDL_TimerMap *prev, *entry; SDL_TimerMap *prev, *entry;
@ -471,16 +468,94 @@ SDL_RemoveTimer(SDL_TimerID id)
return SDL_FALSE; return SDL_FALSE;
} }
#endif /* !defined(__EMSCRIPTEN__) || !SDL_THREADS_DISABLED */
static Uint64 tick_start;
static Uint64 tick_freq;
#if defined(SDL_TIMER_WINDOWS) && \
!defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
#include <timeapi.h>
#define HAVE_TIME_BEGIN_PERIOD
#endif #endif
/* This is a legacy support function; SDL_GetTicks() returns a Uint32, static void SDL_SetSystemTimerResolutionMS(int period)
which wraps back to zero every ~49 days. The newer SDL_GetTicks64()
doesn't have this problem, so we just wrap that function and clamp to
the low 32-bits for binary compatibility. */
Uint32
SDL_GetTicks(void)
{ {
return (Uint32)(SDL_GetTicks64() & 0xFFFFFFFF); #ifdef HAVE_TIME_BEGIN_PERIOD
static int timer_period = 0;
if (period != timer_period) {
if (timer_period) {
timeEndPeriod((UINT)timer_period);
}
timer_period = period;
if (timer_period) {
timeBeginPeriod((UINT)timer_period);
}
}
#endif /* HAVE_TIME_BEGIN_PERIOD */
}
static void SDLCALL SDL_TimerResolutionChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
int period;
/* Unless the hint says otherwise, let's have good sleep precision */
if (hint && *hint) {
period = SDL_atoi(hint);
} else {
period = 1;
}
if (period || oldValue != hint) {
SDL_SetSystemTimerResolutionMS(period);
}
}
void SDL_TicksInit(void)
{
if (tick_start) {
return;
}
/* If we didn't set a precision, set it high. This affects lots of things
on Windows besides the SDL timers, like audio callbacks, etc. */
SDL_AddHintCallback(SDL_HINT_TIMER_RESOLUTION,
SDL_TimerResolutionChanged, NULL);
tick_freq = SDL_GetPerformanceFrequency();
tick_start = SDL_GetPerformanceCounter();
}
void SDL_TicksQuit(void)
{
SDL_DelHintCallback(SDL_HINT_TIMER_RESOLUTION,
SDL_TimerResolutionChanged, NULL);
SDL_SetSystemTimerResolutionMS(0); /* always release our timer resolution request. */
tick_start = 0;
}
Uint64
SDL_GetTicksNS(void)
{
if (!tick_start) {
SDL_TicksInit();
}
return ((SDL_GetPerformanceCounter() - tick_start) * SDL_NS_PER_SECOND) / tick_freq;
}
Uint64 SDL_GetTicks(void)
{
return SDL_NS_TO_MS(SDL_GetTicksNS());
}
void SDL_Delay(Uint32 ms)
{
SDL_DelayNS(SDL_MS_TO_NS(ms));
} }
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View File

@ -22,45 +22,20 @@
#if defined(SDL_TIMER_DUMMY) || defined(SDL_TIMERS_DISABLED) #if defined(SDL_TIMER_DUMMY) || defined(SDL_TIMERS_DISABLED)
static SDL_bool ticks_started = SDL_FALSE;
void SDL_TicksInit(void)
{
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64 Uint64
SDL_GetTicks64(void) SDL_GetPerformanceCounter(void)
{ {
if (!ticks_started) {
SDL_TicksInit();
}
SDL_Unsupported(); SDL_Unsupported();
return 0; return 0;
} }
Uint64
SDL_GetPerformanceCounter(void)
{
return SDL_GetTicks();
}
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
return 1000; return 1;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
SDL_Unsupported(); SDL_Unsupported();
} }

View File

@ -24,34 +24,6 @@
#include <kernel/OS.h> #include <kernel/OS.h>
static bigtime_t start;
static SDL_bool ticks_started = SDL_FALSE;
void SDL_TicksInit(void)
{
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
/* Set first ticks value */
start = system_time();
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
if (!ticks_started) {
SDL_TicksInit();
}
return (Uint64)((system_time() - start) / 1000);
}
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
@ -62,12 +34,12 @@ SDL_GetPerformanceCounter(void)
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
return 1000000; return SDL_US_PER_SECOND;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
snooze(ms * 1000); snooze((bigtime_t)SDL_NS_TO_US(ns));
} }
#endif /* SDL_TIMER_HAIKU */ #endif /* SDL_TIMER_HAIKU */

View File

@ -24,37 +24,6 @@
#include <3ds.h> #include <3ds.h>
static SDL_bool ticks_started = SDL_FALSE;
static u64 start_tick;
#define NSEC_PER_MSEC 1000000ULL
void SDL_TicksInit(void)
{
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
start_tick = svcGetSystemTick();
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
u64 elapsed;
if (!ticks_started) {
SDL_TicksInit();
}
elapsed = svcGetSystemTick() - start_tick;
return elapsed / CPU_TICKS_PER_MSEC;
}
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
@ -68,9 +37,9 @@ SDL_GetPerformanceFrequency(void)
return SYSCLOCK_ARM11; return SYSCLOCK_ARM11;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
svcSleepThread(ms * NSEC_PER_MSEC); svcSleepThread(ns);
} }
#endif /* SDL_TIMER_N3DS */ #endif /* SDL_TIMER_N3DS */

View File

@ -25,63 +25,33 @@
#include <e32std.h> #include <e32std.h>
#include <e32hal.h> #include <e32hal.h>
static SDL_bool ticks_started = SDL_FALSE; static TUint start_tick = 0;
static TUint start = 0;
static TInt tickPeriodMilliSeconds;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void SDL_TicksInit(void)
{
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
start = User::TickCount();
TTimeIntervalMicroSeconds32 period;
TInt tmp = UserHal::TickPeriod(period);
(void)tmp; /* Suppress redundant warning. */
tickPeriodMilliSeconds = period.Int() / 1000;
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
if (!ticks_started) {
SDL_TicksInit();
}
TUint deltaTics = User::TickCount() - start;
// Overlaps early, but should do the trick for now.
return (Uint64)(deltaTics * tickPeriodMilliSeconds);
}
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
{ {
/* FIXME: Need to account for 32-bit wrapping */
return (Uint64)User::TickCount(); return (Uint64)User::TickCount();
} }
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
return 1000000; return SDL_US_PER_SECOND;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
User::After(TTimeIntervalMicroSeconds32(ms * 1000)); const Uint64 max_delay = 0x7fffffff * SDL_NS_PER_US;
if (ns > max_delay) {
ns = max_delay;
}
User::After(TTimeIntervalMicroSeconds32((TInt)SDL_NS_TO_US(ns)));
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -28,54 +28,24 @@
#include <timer.h> #include <timer.h>
#include <sys/time.h> #include <sys/time.h>
static uint64_t start;
static SDL_bool ticks_started = SDL_FALSE;
void SDL_TicksInit(void)
{
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
start = GetTimerSystemTime();
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
uint64_t now;
if (!ticks_started) {
SDL_TicksInit();
}
now = GetTimerSystemTime();
return (Uint64)((now - start) / (kBUSCLK / CLOCKS_PER_SEC));
}
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
{ {
return SDL_GetTicks64(); return GetTimerSystemTime();
} }
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
return 1000; return kBUSCLK;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
struct timespec tv = { 0 }; struct timespec tv;
tv.tv_sec = ms / 1000; tv.tv_sec = (ns / SDL_NS_PER_SECOND);
tv.tv_nsec = (ms % 1000) * 1000000; tv.tv_nsec = (ns % SDL_NS_PER_SECOND);
nanosleep(&tv, NULL); nanosleep(&tv, NULL);
} }

View File

@ -28,56 +28,33 @@
#include <sys/time.h> #include <sys/time.h>
#include <pspthreadman.h> #include <pspthreadman.h>
static struct timeval start;
static SDL_bool ticks_started = SDL_FALSE;
void SDL_TicksInit(void)
{
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
gettimeofday(&start, NULL);
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
struct timeval now;
if (!ticks_started) {
SDL_TicksInit();
}
gettimeofday(&now, NULL);
return (Uint64)(((Sint64)(now.tv_sec - start.tv_sec) * 1000) + ((now.tv_usec - start.tv_usec) / 1000));
}
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
{ {
return SDL_GetTicks64(); Uint64 ticks;
struct timeval now;
gettimeofday(&now, NULL);
ticks = now.tv_sec;
ticks *= SDL_US_PER_SECOND;
ticks += now.tv_usec;
return ticks;
} }
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
return 1000; return SDL_US_PER_SECOND;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
const Uint32 max_delay = 0xffffffffUL / 1000; const Uint64 max_delay = 0xffffffff * SDL_NS_PER_US;
if (ms > max_delay) { if (ns > max_delay) {
ms = max_delay; ns = max_delay;
} }
sceKernelDelayThreadCB(ms * 1000); sceKernelDelayThreadCB((SceUInt)SDL_NS_TO_US(ns));
} }
#endif /* SDL_TIMER_PSP */ #endif /* SDL_TIMER_PSP */

View File

@ -61,76 +61,34 @@
#endif #endif
/* The first ticks value of the application */ /* The first ticks value of the application */
#if HAVE_CLOCK_GETTIME #if !defined(HAVE_CLOCK_GETTIME) && defined(__APPLE__)
static struct timespec start_ts;
#elif defined(__APPLE__)
static uint64_t start_mach;
mach_timebase_info_data_t mach_base_info; mach_timebase_info_data_t mach_base_info;
#endif #endif
static SDL_bool checked_monotonic_time = SDL_FALSE;
static SDL_bool has_monotonic_time = SDL_FALSE; static SDL_bool has_monotonic_time = SDL_FALSE;
static struct timeval start_tv;
static SDL_bool ticks_started = SDL_FALSE;
void SDL_TicksInit(void) static void CheckMonotonicTime(void)
{ {
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
/* Set first ticks value */
#if HAVE_CLOCK_GETTIME #if HAVE_CLOCK_GETTIME
if (clock_gettime(SDL_MONOTONIC_CLOCK, &start_ts) == 0) { struct timespec value;
if (clock_gettime(SDL_MONOTONIC_CLOCK, &value) == 0) {
has_monotonic_time = SDL_TRUE; has_monotonic_time = SDL_TRUE;
} else } else
#elif defined(__APPLE__) #elif defined(__APPLE__)
if (mach_timebase_info(&mach_base_info) == 0) { if (mach_timebase_info(&mach_base_info) == 0) {
has_monotonic_time = SDL_TRUE; has_monotonic_time = SDL_TRUE;
start_mach = mach_absolute_time(); }
} else
#endif #endif
{ checked_monotonic_time = SDL_TRUE;
gettimeofday(&start_tv, NULL);
}
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
if (!ticks_started) {
SDL_TicksInit();
}
if (has_monotonic_time) {
#if HAVE_CLOCK_GETTIME
struct timespec now;
clock_gettime(SDL_MONOTONIC_CLOCK, &now);
return (Uint64)(((Sint64)(now.tv_sec - start_ts.tv_sec) * 1000) + ((now.tv_nsec - start_ts.tv_nsec) / 1000000));
#elif defined(__APPLE__)
const uint64_t now = mach_absolute_time();
return (((now - start_mach) * mach_base_info.numer) / mach_base_info.denom) / 1000000;
#else
SDL_assert(SDL_FALSE);
return 0;
#endif
} else {
struct timeval now;
gettimeofday(&now, NULL);
return (Uint64)(((Sint64)(now.tv_sec - start_tv.tv_sec) * 1000) + ((now.tv_usec - start_tv.tv_usec) / 1000));
}
} }
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
{ {
Uint64 ticks; Uint64 ticks;
if (!ticks_started) {
SDL_TicksInit(); if (!checked_monotonic_time) {
CheckMonotonicTime();
} }
if (has_monotonic_time) { if (has_monotonic_time) {
@ -139,7 +97,7 @@ SDL_GetPerformanceCounter(void)
clock_gettime(SDL_MONOTONIC_CLOCK, &now); clock_gettime(SDL_MONOTONIC_CLOCK, &now);
ticks = now.tv_sec; ticks = now.tv_sec;
ticks *= 1000000000; ticks *= SDL_NS_PER_SECOND;
ticks += now.tv_nsec; ticks += now.tv_nsec;
#elif defined(__APPLE__) #elif defined(__APPLE__)
ticks = mach_absolute_time(); ticks = mach_absolute_time();
@ -152,7 +110,7 @@ SDL_GetPerformanceCounter(void)
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
ticks = now.tv_sec; ticks = now.tv_sec;
ticks *= 1000000; ticks *= SDL_US_PER_SECOND;
ticks += now.tv_usec; ticks += now.tv_usec;
} }
return ticks; return ticks;
@ -161,30 +119,30 @@ SDL_GetPerformanceCounter(void)
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
if (!ticks_started) { if (!checked_monotonic_time) {
SDL_TicksInit(); CheckMonotonicTime();
} }
if (has_monotonic_time) { if (has_monotonic_time) {
#if HAVE_CLOCK_GETTIME #if HAVE_CLOCK_GETTIME
return 1000000000; return SDL_NS_PER_SECOND;
#elif defined(__APPLE__) #elif defined(__APPLE__)
Uint64 freq = mach_base_info.denom; Uint64 freq = mach_base_info.denom;
freq *= 1000000000; freq *= SDL_NS_PER_SECOND;
freq /= mach_base_info.numer; freq /= mach_base_info.numer;
return freq; return freq;
#endif #endif
} }
return 1000000; return SDL_US_PER_SECOND;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
int was_error; int was_error;
#if HAVE_NANOSLEEP #if HAVE_NANOSLEEP
struct timespec elapsed, tv; struct timespec tv, remaining;
#else #else
struct timeval tv; struct timeval tv;
Uint64 then, now, elapsed; Uint64 then, now, elapsed;
@ -193,36 +151,36 @@ void SDL_Delay(Uint32 ms)
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) { if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
/* pseudo-synchronous pause, used directly or through e.g. SDL_WaitEvent */ /* pseudo-synchronous pause, used directly or through e.g. SDL_WaitEvent */
emscripten_sleep(ms); emscripten_sleep(ns / SDL_NS_PER_MS);
return; return;
} }
#endif #endif
/* Set the timeout interval */ /* Set the timeout interval */
#if HAVE_NANOSLEEP #if HAVE_NANOSLEEP
elapsed.tv_sec = ms / 1000; remaining.tv_sec = (ns / SDL_NS_PER_SECOND);
elapsed.tv_nsec = (ms % 1000) * 1000000; remaining.tv_nsec = (ns % SDL_NS_PER_SECOND);
#else #else
then = SDL_GetTicks64(); then = SDL_GetTicksNS();
#endif #endif
do { do {
errno = 0; errno = 0;
#if HAVE_NANOSLEEP #if HAVE_NANOSLEEP
tv.tv_sec = elapsed.tv_sec; tv.tv_sec = remaining.tv_sec;
tv.tv_nsec = elapsed.tv_nsec; tv.tv_nsec = remaining.tv_nsec;
was_error = nanosleep(&tv, &elapsed); was_error = nanosleep(&tv, &remaining);
#else #else
/* Calculate the time interval left (in case of interrupt) */ /* Calculate the time interval left (in case of interrupt) */
now = SDL_GetTicks64(); now = SDL_GetTicksNS();
elapsed = (now - then); elapsed = (now - then);
then = now; then = now;
if (elapsed >= ((Uint64)ms)) { if (elapsed >= ns) {
break; break;
} }
ms -= (Uint32)elapsed; ns -= elapsed;
tv.tv_sec = ms / 1000; tv.tv_sec = (ns / SDL_NS_PER_SECOND)
tv.tv_usec = (ms % 1000) * 1000; tv.tv_usec = SDL_NS_TO_US(ns % SDL_NS_PER_SECOND);
was_error = select(0, NULL, NULL, NULL, &tv); was_error = select(0, NULL, NULL, NULL, &tv);
#endif /* HAVE_NANOSLEEP */ #endif /* HAVE_NANOSLEEP */

View File

@ -28,36 +28,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <psp2/kernel/processmgr.h> #include <psp2/kernel/processmgr.h>
static uint64_t start;
static SDL_bool ticks_started = SDL_FALSE;
void SDL_TicksInit(void)
{
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
start = sceKernelGetProcessTimeWide();
}
void SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
uint64_t now;
if (!ticks_started) {
SDL_TicksInit();
}
now = sceKernelGetProcessTimeWide();
return (Uint64)((now - start) / 1000);
}
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
@ -68,16 +38,16 @@ SDL_GetPerformanceCounter(void)
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
return 1000000; return SDL_US_PER_SECOND;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
const Uint32 max_delay = 0xffffffffUL / 1000; const Uint64 max_delay = 0xffffffff * SDL_NS_PER_US;
if (ms > max_delay) { if (ns > max_delay) {
ms = max_delay; ns = max_delay;
} }
sceKernelDelayThreadCB(ms * 1000); sceKernelDelayThreadCB((SceUInt)SDL_NS_TO_US(ns));
} }
#endif /* SDL_TIMER_VITA */ #endif /* SDL_TIMER_VITA */

View File

@ -23,99 +23,7 @@
#ifdef SDL_TIMER_WINDOWS #ifdef SDL_TIMER_WINDOWS
#include "../../core/windows/SDL_windows.h" #include "../../core/windows/SDL_windows.h"
#include <mmsystem.h>
/* The first (low-resolution) ticks value of the application */
static DWORD start = 0;
static BOOL ticks_started = FALSE;
/* The first high-resolution ticks value of the application */
static LARGE_INTEGER start_ticks;
/* The number of ticks per second of the high-resolution performance counter */
static LARGE_INTEGER ticks_per_second;
static void SDL_SetSystemTimerResolution(const UINT uPeriod)
{
#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
static UINT timer_period = 0;
if (uPeriod != timer_period) {
if (timer_period) {
timeEndPeriod(timer_period);
}
timer_period = uPeriod;
if (timer_period) {
timeBeginPeriod(timer_period);
}
}
#endif
}
static void SDLCALL SDL_TimerResolutionChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
UINT uPeriod;
/* Unless the hint says otherwise, let's have good sleep precision */
if (hint && *hint) {
uPeriod = SDL_atoi(hint);
} else {
uPeriod = 1;
}
if (uPeriod || oldValue != hint) {
SDL_SetSystemTimerResolution(uPeriod);
}
}
void SDL_TicksInit(void)
{
BOOL rc;
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
/* if we didn't set a precision, set it high. This affects lots of things
on Windows besides the SDL timers, like audio callbacks, etc. */
SDL_AddHintCallback(SDL_HINT_TIMER_RESOLUTION,
SDL_TimerResolutionChanged, NULL);
/* Set first ticks value */
/* QueryPerformanceCounter allegedly is always available and reliable as of WinXP,
so we'll rely on it here.
*/
rc = QueryPerformanceFrequency(&ticks_per_second);
SDL_assert(rc != 0); /* this should _never_ fail if you're on XP or later. */
QueryPerformanceCounter(&start_ticks);
}
void SDL_TicksQuit(void)
{
SDL_DelHintCallback(SDL_HINT_TIMER_RESOLUTION,
SDL_TimerResolutionChanged, NULL);
SDL_SetSystemTimerResolution(0); /* always release our timer resolution request. */
start = 0;
ticks_started = SDL_FALSE;
}
Uint64
SDL_GetTicks64(void)
{
LARGE_INTEGER now;
BOOL rc;
if (!ticks_started) {
SDL_TicksInit();
}
rc = QueryPerformanceCounter(&now);
SDL_assert(rc != 0); /* this should _never_ fail if you're on XP or later. */
return (Uint64)(((now.QuadPart - start_ticks.QuadPart) * 1000) / ticks_per_second.QuadPart);
}
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
@ -135,7 +43,7 @@ SDL_GetPerformanceFrequency(void)
return (Uint64)frequency.QuadPart; return (Uint64)frequency.QuadPart;
} }
void SDL_Delay(Uint32 ms) void SDL_DelayNS(Uint64 ns)
{ {
/* CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag was added in Windows 10 version 1803. /* CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag was added in Windows 10 version 1803.
* *
@ -155,7 +63,7 @@ void SDL_Delay(Uint32 ms)
HANDLE timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); HANDLE timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
if (timer) { if (timer) {
LARGE_INTEGER due_time; LARGE_INTEGER due_time;
due_time.QuadPart = -(ms * 10000LL); due_time.QuadPart = -((LONGLONG)ns / 100);
if (SetWaitableTimerEx(timer, &due_time, 0, NULL, NULL, NULL, 0)) { if (SetWaitableTimerEx(timer, &due_time, 0, NULL, NULL, NULL, 0)) {
WaitForSingleObject(timer, INFINITE); WaitForSingleObject(timer, INFINITE);
} }
@ -163,19 +71,23 @@ void SDL_Delay(Uint32 ms)
return; return;
} }
#endif #endif
{
const Uint64 max_delay = 0xffffffff * SDL_NS_PER_MS;
if (ns > max_delay) {
ns = max_delay;
}
#if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723) #if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723)
static HANDLE mutex = 0; static HANDLE mutex = 0;
if (!mutex) { if (!mutex) {
mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS); mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS);
} }
WaitForSingleObjectEx(mutex, ms, FALSE); WaitForSingleObjectEx(mutex, (DWORD)SDL_NS_TO_MS(ns), FALSE);
#else #else
if (!ticks_started) { Sleep((DWORD)SDL_NS_TO_MS(ns));
SDL_TicksInit();
}
Sleep(ms);
#endif #endif
}
} }
#endif /* SDL_TIMER_WINDOWS */ #endif /* SDL_TIMER_WINDOWS */

View File

@ -294,7 +294,7 @@ struct SDL_VideoDevice
/* /*
* Event manager functions * Event manager functions
*/ */
int (*WaitEventTimeout)(_THIS, int timeout); int (*WaitEventTimeout)(_THIS, Sint64 timeoutNS);
void (*SendWakeupEvent)(_THIS, SDL_Window *window); void (*SendWakeupEvent)(_THIS, SDL_Window *window);
void (*PumpEvents)(_THIS); void (*PumpEvents)(_THIS);

View File

@ -25,7 +25,7 @@
extern void Cocoa_RegisterApp(void); extern void Cocoa_RegisterApp(void);
extern void Cocoa_PumpEvents(_THIS); extern void Cocoa_PumpEvents(_THIS);
extern int Cocoa_WaitEventTimeout(_THIS, int timeout); extern int Cocoa_WaitEventTimeout(_THIS, Sint64 timeoutNS);
extern void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window); extern void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window);
extern void Cocoa_SuspendScreenSaver(_THIS); extern void Cocoa_SuspendScreenSaver(_THIS);

View File

@ -523,13 +523,13 @@ int Cocoa_PumpEventsUntilDate(_THIS, NSDate *expiration, bool accumulate)
return 1; return 1;
} }
int Cocoa_WaitEventTimeout(_THIS, int timeout) int Cocoa_WaitEventTimeout(_THIS, Sint64 timeoutNS)
{ {
@autoreleasepool { @autoreleasepool {
if (timeout > 0) { if (timeoutNS > 0) {
NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow:(double)timeout / 1000.0]; NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow:(double)timeoutNS / SDL_NS_PER_SECOND];
return Cocoa_PumpEventsUntilDate(_this, limitDate, false); return Cocoa_PumpEventsUntilDate(_this, limitDate, false);
} else if (timeout == 0) { } else if (timeoutNS == 0) {
return Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], false); return Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], false);
} else { } else {
while (Cocoa_PumpEventsUntilDate(_this, [NSDate distantFuture], false) == 0) { while (Cocoa_PumpEventsUntilDate(_this, [NSDate distantFuture], false) == 0) {

View File

@ -500,7 +500,7 @@ int Cocoa_GL_SwapWindow(_THIS, SDL_Window *window)
SDL_UnlockMutex(nscontext->swapIntervalMutex); SDL_UnlockMutex(nscontext->swapIntervalMutex);
} }
/*{ static Uint64 prev = 0; const Uint64 now = SDL_GetTicks64(); const unsigned int diff = (unsigned int) (now - prev); prev = now; printf("GLSWAPBUFFERS TICKS %u\n", diff); }*/ /*{ static Uint64 prev = 0; const Uint64 now = SDL_GetTicks(); const unsigned int diff = (unsigned int) (now - prev); prev = now; printf("GLSWAPBUFFERS TICKS %u\n", diff); }*/
/* on 10.14 ("Mojave") and later, this deadlocks if two contexts in two /* on 10.14 ("Mojave") and later, this deadlocks if two contexts in two
threads try to swap at the same time, so put a mutex around it. */ threads try to swap at the same time, so put a mutex around it. */

View File

@ -252,7 +252,7 @@
@end @end
static Uint32 s_moveHack; static Uint64 s_moveHack;
static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r) static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r)
{ {
@ -1896,7 +1896,7 @@ void Cocoa_SetWindowPosition(_THIS, SDL_Window *window)
SDL_WindowData *windata = (__bridge SDL_WindowData *)window->driverdata; SDL_WindowData *windata = (__bridge SDL_WindowData *)window->driverdata;
NSWindow *nswindow = windata.nswindow; NSWindow *nswindow = windata.nswindow;
NSRect rect; NSRect rect;
Uint32 moveHack; Uint64 moveHack;
rect.origin.x = window->x; rect.origin.x = window->x;
rect.origin.y = window->y; rect.origin.y = window->y;
@ -1919,7 +1919,7 @@ void Cocoa_SetWindowSize(_THIS, SDL_Window *window)
SDL_WindowData *windata = (__bridge SDL_WindowData *)window->driverdata; SDL_WindowData *windata = (__bridge SDL_WindowData *)window->driverdata;
NSWindow *nswindow = windata.nswindow; NSWindow *nswindow = windata.nswindow;
NSRect rect; NSRect rect;
Uint32 moveHack; Uint64 moveHack;
/* Cocoa will resize the window from the bottom-left rather than the /* Cocoa will resize the window from the bottom-left rather than the
* top-left when -[nswindow setContentSize:] is used, so we must set the * top-left when -[nswindow setContentSize:] is used, so we must set the

View File

@ -37,7 +37,7 @@
/* FIXME: This is arbitrary, but we want this to be less than a frame because /* FIXME: This is arbitrary, but we want this to be less than a frame because
* any longer can potentially spin an infinite loop of PumpEvents (!) * any longer can potentially spin an infinite loop of PumpEvents (!)
*/ */
#define PIPE_MS_TIMEOUT 14 #define PIPE_TIMEOUT_NS SDL_MS_TO_NS(14)
static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_t *pos) static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_t *pos)
{ {
@ -49,7 +49,7 @@ static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_
sigset_t old_sig_set; sigset_t old_sig_set;
struct timespec zerotime = { 0 }; struct timespec zerotime = { 0 };
ready = SDL_IOReady(fd, SDL_IOR_WRITE, PIPE_MS_TIMEOUT); ready = SDL_IOReady(fd, SDL_IOR_WRITE, PIPE_TIMEOUT_NS);
sigemptyset(&sig_set); sigemptyset(&sig_set);
sigaddset(&sig_set, SIGPIPE); sigaddset(&sig_set, SIGPIPE);
@ -94,7 +94,7 @@ static ssize_t read_pipe(int fd, void **buffer, size_t *total_length, SDL_bool n
ssize_t bytes_read = 0; ssize_t bytes_read = 0;
size_t pos = 0; size_t pos = 0;
ready = SDL_IOReady(fd, SDL_IOR_READ, PIPE_MS_TIMEOUT); ready = SDL_IOReady(fd, SDL_IOR_READ, PIPE_TIMEOUT_NS);
if (ready == 0) { if (ready == 0) {
bytes_read = SDL_SetError("Pipe timeout"); bytes_read = SDL_SetError("Pipe timeout");

View File

@ -270,7 +270,7 @@ static int dispatch_queued_events(SDL_VideoData *viddata)
return ret >= 0 ? 1 : ret; return ret >= 0 ? 1 : ret;
} }
int Wayland_WaitEventTimeout(_THIS, int timeout) int Wayland_WaitEventTimeout(_THIS, Sint64 timeoutNS)
{ {
SDL_VideoData *d = _this->driverdata; SDL_VideoData *d = _this->driverdata;
struct SDL_WaylandInput *input = d->input; struct SDL_WaylandInput *input = d->input;
@ -286,16 +286,16 @@ int Wayland_WaitEventTimeout(_THIS, int timeout)
/* If key repeat is active, we'll need to cap our maximum wait time to handle repeats */ /* If key repeat is active, we'll need to cap our maximum wait time to handle repeats */
if (input && keyboard_repeat_is_set(&input->keyboard_repeat)) { if (input && keyboard_repeat_is_set(&input->keyboard_repeat)) {
uint32_t elapsed = SDL_GetTicks() - input->keyboard_repeat.sdl_press_time; uint32_t elapsed = (uint32_t)(SDL_GetTicks() - input->keyboard_repeat.sdl_press_time);
if (keyboard_repeat_handle(&input->keyboard_repeat, elapsed)) { if (keyboard_repeat_handle(&input->keyboard_repeat, elapsed)) {
/* A repeat key event was already due */ /* A repeat key event was already due */
return 1; return 1;
} else { } else {
uint32_t next_repeat_wait_time = (input->keyboard_repeat.next_repeat_ms - elapsed) + 1; uint32_t next_repeat_wait_time = (input->keyboard_repeat.next_repeat_ms - elapsed) + 1;
if (timeout >= 0) { if (timeoutNS >= 0) {
timeout = SDL_min(timeout, next_repeat_wait_time); timeoutNS = SDL_min(timeoutNS, SDL_MS_TO_NS(next_repeat_wait_time));
} else { } else {
timeout = next_repeat_wait_time; timeoutNS = SDL_MS_TO_NS(next_repeat_wait_time);
} }
key_repeat_active = SDL_TRUE; key_repeat_active = SDL_TRUE;
} }
@ -305,7 +305,7 @@ int Wayland_WaitEventTimeout(_THIS, int timeout)
* If the default queue is empty, it will prepare us for our SDL_IOReady() call. */ * If the default queue is empty, it will prepare us for our SDL_IOReady() call. */
if (WAYLAND_wl_display_prepare_read(d->display) == 0) { if (WAYLAND_wl_display_prepare_read(d->display) == 0) {
/* Use SDL_IOR_NO_RETRY to ensure SIGINT will break us out of our wait */ /* Use SDL_IOR_NO_RETRY to ensure SIGINT will break us out of our wait */
int err = SDL_IOReady(WAYLAND_wl_display_get_fd(d->display), SDL_IOR_READ | SDL_IOR_NO_RETRY, timeout); int err = SDL_IOReady(WAYLAND_wl_display_get_fd(d->display), SDL_IOR_READ | SDL_IOR_NO_RETRY, timeoutNS);
if (err > 0) { if (err > 0) {
/* There are new events available to read */ /* There are new events available to read */
WAYLAND_wl_display_read_events(d->display); WAYLAND_wl_display_read_events(d->display);
@ -316,7 +316,7 @@ int Wayland_WaitEventTimeout(_THIS, int timeout)
/* If key repeat is active, we might have woken up to generate a key event */ /* If key repeat is active, we might have woken up to generate a key event */
if (key_repeat_active) { if (key_repeat_active) {
uint32_t elapsed = SDL_GetTicks() - input->keyboard_repeat.sdl_press_time; uint32_t elapsed = (uint32_t)(SDL_GetTicks() - input->keyboard_repeat.sdl_press_time);
if (keyboard_repeat_handle(&input->keyboard_repeat, elapsed)) { if (keyboard_repeat_handle(&input->keyboard_repeat, elapsed)) {
return 1; return 1;
} }
@ -375,7 +375,7 @@ void Wayland_PumpEvents(_THIS)
err = WAYLAND_wl_display_dispatch_pending(d->display); err = WAYLAND_wl_display_dispatch_pending(d->display);
if (input && keyboard_repeat_is_set(&input->keyboard_repeat)) { if (input && keyboard_repeat_is_set(&input->keyboard_repeat)) {
uint32_t elapsed = SDL_GetTicks() - input->keyboard_repeat.sdl_press_time; uint32_t elapsed = (uint32_t)(SDL_GetTicks() - input->keyboard_repeat.sdl_press_time);
keyboard_repeat_handle(&input->keyboard_repeat, elapsed); keyboard_repeat_handle(&input->keyboard_repeat, elapsed);
} }

View File

@ -76,7 +76,7 @@ typedef struct
SDL_bool is_key_down; SDL_bool is_key_down;
uint32_t key; uint32_t key;
uint32_t wl_press_time; // Key press time as reported by the Wayland API uint32_t wl_press_time; // Key press time as reported by the Wayland API
uint32_t sdl_press_time; // Key press time expressed in SDL ticks Uint64 sdl_press_time; // Key press time expressed in SDL ticks
uint32_t next_repeat_ms; uint32_t next_repeat_ms;
uint32_t scancode; uint32_t scancode;
char text[8]; char text[8];
@ -148,7 +148,7 @@ struct SDL_WaylandInput
extern void Wayland_PumpEvents(_THIS); extern void Wayland_PumpEvents(_THIS);
extern void Wayland_SendWakeupEvent(_THIS, SDL_Window *window); extern void Wayland_SendWakeupEvent(_THIS, SDL_Window *window);
extern int Wayland_WaitEventTimeout(_THIS, int timeout); extern int Wayland_WaitEventTimeout(_THIS, Sint64 timeoutNS);
extern void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version); extern void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
extern void Wayland_add_primary_selection_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version); extern void Wayland_add_primary_selection_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);

View File

@ -125,9 +125,9 @@ int Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
struct wl_display *display = videodata->display; struct wl_display *display = videodata->display;
SDL_VideoDisplay *sdldisplay = SDL_GetDisplayForWindow(window); SDL_VideoDisplay *sdldisplay = SDL_GetDisplayForWindow(window);
/* ~10 frames (or 1 sec), so we'll progress even if throttled to zero. */ /* ~10 frames (or 1 sec), so we'll progress even if throttled to zero. */
const Uint32 max_wait = SDL_GetTicks() + (sdldisplay->current_mode.refresh_rate ? (10000 / sdldisplay->current_mode.refresh_rate) : 1000); const Uint64 max_wait = SDL_GetTicksNS() + (sdldisplay->current_mode.refresh_rate ? ((SDL_NS_PER_SECOND * 10) / sdldisplay->current_mode.refresh_rate) : SDL_NS_PER_SECOND);
while (SDL_AtomicGet(&data->swap_interval_ready) == 0) { while (SDL_AtomicGet(&data->swap_interval_ready) == 0) {
Uint32 now; Uint64 now;
WAYLAND_wl_display_flush(display); WAYLAND_wl_display_flush(display);
@ -141,8 +141,8 @@ int Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
/* Beyond this point, we must either call wl_display_cancel_read() or wl_display_read_events() */ /* Beyond this point, we must either call wl_display_cancel_read() or wl_display_read_events() */
now = SDL_GetTicks(); now = SDL_GetTicksNS();
if (SDL_TICKS_PASSED(now, max_wait)) { if (now >= max_wait) {
/* Timeout expired. Cancel the read. */ /* Timeout expired. Cancel the read. */
WAYLAND_wl_display_cancel_read(display); WAYLAND_wl_display_cancel_read(display);
break; break;

View File

@ -1707,8 +1707,8 @@ static void WIN_UpdateClipCursorForWindows()
{ {
SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *window; SDL_Window *window;
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
const Uint32 CLIPCURSOR_UPDATE_INTERVAL_MS = 3000; const int CLIPCURSOR_UPDATE_INTERVAL_MS = 3000;
if (_this) { if (_this) {
for (window = _this->windows; window; window = window->next) { for (window = _this->windows; window; window = window->next) {
@ -1717,7 +1717,7 @@ static void WIN_UpdateClipCursorForWindows()
if (data->skip_update_clipcursor) { if (data->skip_update_clipcursor) {
data->skip_update_clipcursor = SDL_FALSE; data->skip_update_clipcursor = SDL_FALSE;
WIN_UpdateClipCursor(window); WIN_UpdateClipCursor(window);
} else if ((now - data->last_updated_clipcursor) >= CLIPCURSOR_UPDATE_INTERVAL_MS) { } else if (now >= (data->last_updated_clipcursor + CLIPCURSOR_UPDATE_INTERVAL_MS)) {
WIN_UpdateClipCursor(window); WIN_UpdateClipCursor(window);
} }
} }
@ -1765,17 +1765,17 @@ void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata)
g_WindowsMessageHookData = userdata; g_WindowsMessageHookData = userdata;
} }
int WIN_WaitEventTimeout(_THIS, int timeout) int WIN_WaitEventTimeout(_THIS, Sint64 timeoutNS)
{ {
MSG msg; MSG msg;
if (g_WindowsEnableMessageLoop) { if (g_WindowsEnableMessageLoop) {
BOOL message_result; BOOL message_result;
UINT_PTR timer_id = 0; UINT_PTR timer_id = 0;
if (timeout > 0) { if (timeoutNS > 0) {
timer_id = SetTimer(NULL, 0, timeout, NULL); timer_id = SetTimer(NULL, 0, (UINT)SDL_NS_TO_MS(timeoutNS), NULL);
message_result = GetMessage(&msg, 0, 0, 0); message_result = GetMessage(&msg, 0, 0, 0);
KillTimer(NULL, timer_id); KillTimer(NULL, timer_id);
} else if (timeout == 0) { } else if (timeoutNS == 0) {
message_result = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); message_result = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
} else { } else {
message_result = GetMessage(&msg, 0, 0, 0); message_result = GetMessage(&msg, 0, 0, 0);
@ -1806,6 +1806,9 @@ void WIN_SendWakeupEvent(_THIS, SDL_Window *window)
PostMessage(data->hwnd, data->videodata->_SDL_WAKEUP, 0, 0); PostMessage(data->hwnd, data->videodata->_SDL_WAKEUP, 0, 0);
} }
/* Used to compare Windows message timestamps */
#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0)
void WIN_PumpEvents(_THIS) void WIN_PumpEvents(_THIS)
{ {
MSG msg; MSG msg;

View File

@ -32,7 +32,7 @@ extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam); LPARAM lParam);
extern void WIN_PumpEvents(_THIS); extern void WIN_PumpEvents(_THIS);
extern void WIN_SendWakeupEvent(_THIS, SDL_Window *window); extern void WIN_SendWakeupEvent(_THIS, SDL_Window *window);
extern int WIN_WaitEventTimeout(_THIS, int timeout); extern int WIN_WaitEventTimeout(_THIS, Sint64 timeoutNS);
#endif /* SDL_windowsevents_h_ */ #endif /* SDL_windowsevents_h_ */

View File

@ -55,7 +55,7 @@ typedef struct
SDL_bool in_title_click; SDL_bool in_title_click;
Uint8 focus_click_pending; Uint8 focus_click_pending;
SDL_bool skip_update_clipcursor; SDL_bool skip_update_clipcursor;
Uint32 last_updated_clipcursor; Uint64 last_updated_clipcursor;
SDL_bool mouse_relative_mode_center; SDL_bool mouse_relative_mode_center;
SDL_bool windowed_mode_was_maximized; SDL_bool windowed_mode_was_maximized;
SDL_bool in_window_deactivation; SDL_bool in_window_deactivation;

View File

@ -151,8 +151,8 @@ static char *GetSlectionText(_THIS, Atom selection_type)
unsigned long overflow; unsigned long overflow;
unsigned char *src; unsigned char *src;
char *text; char *text;
Uint32 waitStart; Uint64 waitStart;
Uint32 waitElapsed; Uint64 waitElapsed;
text = NULL; text = NULL;

View File

@ -1338,7 +1338,7 @@ static void X11_DispatchEvent(_THIS, XEvent *xevent)
} }
if (data->last_focus_event_time) { if (data->last_focus_event_time) {
const int X11_FOCUS_CLICK_TIMEOUT = 10; const int X11_FOCUS_CLICK_TIMEOUT = 10;
if (!SDL_TICKS_PASSED(SDL_GetTicks(), data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) { if (SDL_GetTicks() < (data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE); ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
} }
data->last_focus_event_time = 0; data->last_focus_event_time = 0;
@ -1577,8 +1577,8 @@ static void X11_HandleFocusChanges(_THIS)
for (i = 0; i < videodata->numwindows; ++i) { for (i = 0; i < videodata->numwindows; ++i) {
SDL_WindowData *data = videodata->windowlist[i]; SDL_WindowData *data = videodata->windowlist[i];
if (data && data->pending_focus != PENDING_FOCUS_NONE) { if (data && data->pending_focus != PENDING_FOCUS_NONE) {
Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, data->pending_focus_time)) { if (now >= data->pending_focus_time) {
if (data->pending_focus == PENDING_FOCUS_IN) { if (data->pending_focus == PENDING_FOCUS_IN) {
X11_DispatchFocusIn(_this, data); X11_DispatchFocusIn(_this, data);
} else { } else {
@ -1625,7 +1625,7 @@ void X11_SendWakeupEvent(_THIS, SDL_Window *window)
X11_XFlush(req_display); X11_XFlush(req_display);
} }
int X11_WaitEventTimeout(_THIS, int timeout) int X11_WaitEventTimeout(_THIS, Sint64 timeoutNS)
{ {
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
Display *display; Display *display;
@ -1638,11 +1638,11 @@ int X11_WaitEventTimeout(_THIS, int timeout)
X11_XFlush(display); X11_XFlush(display);
if (X11_PollEvent(display, &xevent)) { if (X11_PollEvent(display, &xevent)) {
/* Fall through */ /* Fall through */
} else if (timeout == 0) { } else if (timeoutNS == 0) {
return 0; return 0;
} else { } else {
/* Use SDL_IOR_NO_RETRY to ensure SIGINT will break us out of our wait */ /* Use SDL_IOR_NO_RETRY to ensure SIGINT will break us out of our wait */
int err = SDL_IOReady(ConnectionNumber(display), SDL_IOR_READ | SDL_IOR_NO_RETRY, timeout); int err = SDL_IOReady(ConnectionNumber(display), SDL_IOR_READ | SDL_IOR_NO_RETRY, timeoutNS);
if (err > 0) { if (err > 0) {
if (!X11_PollEvent(display, &xevent)) { if (!X11_PollEvent(display, &xevent)) {
/* Someone may have beat us to reading the fd. Return 1 here to /* Someone may have beat us to reading the fd. Return 1 here to
@ -1682,16 +1682,15 @@ void X11_PumpEvents(_THIS)
int i; int i;
if (data->last_mode_change_deadline) { if (data->last_mode_change_deadline) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) { if (SDL_GetTicks() >= data->last_mode_change_deadline) {
data->last_mode_change_deadline = 0; /* assume we're done. */ data->last_mode_change_deadline = 0; /* assume we're done. */
} }
} }
/* Update activity every 30 seconds to prevent screensaver */ /* Update activity every 30 seconds to prevent screensaver */
if (_this->suspend_screensaver) { if (_this->suspend_screensaver) {
const Uint32 now = SDL_GetTicks(); Uint64 now = SDL_GetTicks();
if (!data->screensaver_activity || if (!data->screensaver_activity || now >= (data->screensaver_activity + 30000)) {
SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
X11_XResetScreenSaver(data->display); X11_XResetScreenSaver(data->display);
#if SDL_USE_LIBDBUS #if SDL_USE_LIBDBUS
@ -1722,7 +1721,7 @@ void X11_PumpEvents(_THIS)
for (i = 0; i < data->numwindows; ++i) { for (i = 0; i < data->numwindows; ++i) {
if (data->windowlist[i] != NULL && if (data->windowlist[i] != NULL &&
data->windowlist[i]->flash_cancel_time && data->windowlist[i]->flash_cancel_time &&
SDL_TICKS_PASSED(SDL_GetTicks(), data->windowlist[i]->flash_cancel_time)) { SDL_GetTicks() >= data->windowlist[i]->flash_cancel_time) {
X11_FlashWindow(_this, data->windowlist[i]->window, SDL_FLASH_CANCEL); X11_FlashWindow(_this, data->windowlist[i]->window, SDL_FLASH_CANCEL);
} }
} }

View File

@ -24,7 +24,7 @@
#define SDL_x11events_h_ #define SDL_x11events_h_
extern void X11_PumpEvents(_THIS); extern void X11_PumpEvents(_THIS);
extern int X11_WaitEventTimeout(_THIS, int timeout); extern int X11_WaitEventTimeout(_THIS, Sint64 timeoutNS);
extern void X11_SendWakeupEvent(_THIS, SDL_Window *window); extern void X11_SendWakeupEvent(_THIS, SDL_Window *window);
extern void X11_SuspendScreenSaver(_THIS); extern void X11_SuspendScreenSaver(_THIS);
extern void X11_ReconcileKeyboardState(_THIS); extern void X11_ReconcileKeyboardState(_THIS);

View File

@ -71,7 +71,7 @@ typedef struct SDL_VideoData
char *classname; char *classname;
pid_t pid; pid_t pid;
XIM im; XIM im;
Uint32 screensaver_activity; Uint64 screensaver_activity;
int numwindows; int numwindows;
SDL_WindowData **windowlist; SDL_WindowData **windowlist;
int windowlistlength; int windowlistlength;
@ -126,7 +126,7 @@ typedef struct SDL_VideoData
SDL_bool broken_pointer_grab; /* true if XGrabPointer seems unreliable. */ SDL_bool broken_pointer_grab; /* true if XGrabPointer seems unreliable. */
Uint32 last_mode_change_deadline; Uint64 last_mode_change_deadline;
SDL_bool global_mouse_changed; SDL_bool global_mouse_changed;
SDL_Point global_mouse_position; SDL_Point global_mouse_position;

View File

@ -62,10 +62,10 @@ static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
} }
static Bool X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg, int timeoutMS) static Bool X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg, int timeoutMS)
{ {
Uint32 start = SDL_GetTicks(); Uint64 start = SDL_GetTicks();
while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) { while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), start + timeoutMS)) { if (SDL_GetTicks() >= (start + timeoutMS)) {
return False; return False;
} }
} }
@ -797,7 +797,7 @@ void X11_SetWindowPosition(_THIS, SDL_Window *window)
Window *children; Window *children;
XWindowAttributes attrs; XWindowAttributes attrs;
int orig_x, orig_y; int orig_x, orig_y;
Uint32 timeout; Uint64 timeout;
X11_XSync(display, False); X11_XSync(display, False);
X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount); X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount);
@ -833,7 +833,7 @@ void X11_SetWindowPosition(_THIS, SDL_Window *window)
} }
} }
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) { if (SDL_GetTicks() >= timeout) {
break; break;
} }
@ -907,7 +907,7 @@ void X11_SetWindowSize(_THIS, SDL_Window *window)
int (*prev_handler)(Display *, XErrorEvent *) = NULL; int (*prev_handler)(Display *, XErrorEvent *) = NULL;
XWindowAttributes attrs; XWindowAttributes attrs;
int orig_w, orig_h; int orig_w, orig_h;
Uint32 timeout; Uint64 timeout;
X11_XSync(display, False); X11_XSync(display, False);
X11_XGetWindowAttributes(display, data->xwindow, &attrs); X11_XGetWindowAttributes(display, data->xwindow, &attrs);
@ -977,7 +977,7 @@ void X11_SetWindowSize(_THIS, SDL_Window *window)
} }
} }
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) { if (SDL_GetTicks() >= timeout) {
break; break;
} }
@ -1377,7 +1377,7 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis
X11_XSync(display, False); X11_XSync(display, False);
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError); prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
timeout = SDL_GetTicks64() + 100; timeout = SDL_GetTicks() + 100;
while (SDL_TRUE) { while (SDL_TRUE) {
int x, y; int x, y;
@ -1404,7 +1404,7 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis
} }
} }
if (SDL_GetTicks64() >= timeout) { if (SDL_GetTicks() >= timeout) {
break; break;
} }
@ -1720,9 +1720,6 @@ int X11_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation)
data->flashing_window = SDL_TRUE; data->flashing_window = SDL_TRUE;
/* On Ubuntu 21.04 this causes a dialog to pop up, so leave it up for a full second so users can see it */ /* On Ubuntu 21.04 this causes a dialog to pop up, so leave it up for a full second so users can see it */
data->flash_cancel_time = SDL_GetTicks() + 1000; data->flash_cancel_time = SDL_GetTicks() + 1000;
if (!data->flash_cancel_time) {
data->flash_cancel_time = 1;
}
} }
break; break;
case SDL_FLASH_UNTIL_FOCUSED: case SDL_FLASH_UNTIL_FOCUSED:

View File

@ -60,16 +60,16 @@ typedef struct
int border_top; int border_top;
int border_bottom; int border_bottom;
SDL_bool mouse_grabbed; SDL_bool mouse_grabbed;
Uint32 last_focus_event_time; Uint64 last_focus_event_time;
PendingFocusEnum pending_focus; PendingFocusEnum pending_focus;
Uint32 pending_focus_time; Uint64 pending_focus_time;
XConfigureEvent last_xconfigure; XConfigureEvent last_xconfigure;
struct SDL_VideoData *videodata; struct SDL_VideoData *videodata;
unsigned long user_time; unsigned long user_time;
Atom xdnd_req; Atom xdnd_req;
Window xdnd_source; Window xdnd_source;
SDL_bool flashing_window; SDL_bool flashing_window;
Uint32 flash_cancel_time; Uint64 flash_cancel_time;
#if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface; EGLSurface egl_surface;
#endif #endif

View File

@ -164,7 +164,7 @@ static int s_nNumAxes;
static AxisState *s_arrAxisState; static AxisState *s_arrAxisState;
static int s_iCurrentBinding; static int s_iCurrentBinding;
static Uint32 s_unPendingAdvanceTime; static Uint64 s_unPendingAdvanceTime;
static SDL_bool s_bBindingComplete; static SDL_bool s_bBindingComplete;
static SDL_Window *window; static SDL_Window *window;
@ -354,7 +354,7 @@ WatchJoystick(SDL_Joystick *joystick)
SDL_Event event; SDL_Event event;
SDL_Rect dst; SDL_Rect dst;
Uint8 alpha = 200, alpha_step = -1; Uint8 alpha = 200, alpha_step = -1;
Uint32 alpha_ticks = 0; Uint64 alpha_ticks = 0;
SDL_JoystickID nJoystickID; SDL_JoystickID nJoystickID;
background_front = LoadTexture(screen, "controllermap.bmp", SDL_FALSE, NULL, NULL); background_front = LoadTexture(screen, "controllermap.bmp", SDL_FALSE, NULL, NULL);
@ -409,7 +409,7 @@ WatchJoystick(SDL_Joystick *joystick)
dst.y = s_arrBindingDisplay[iElement].y; dst.y = s_arrBindingDisplay[iElement].y;
SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h); SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h);
if (SDL_GetTicks() - alpha_ticks > 5) { if (SDL_GetTicks() >= (alpha_ticks + 5)) {
alpha_ticks = SDL_GetTicks(); alpha_ticks = SDL_GetTicks();
alpha += alpha_step; alpha += alpha_step;
if (alpha == 255) { if (alpha == 255) {

View File

@ -127,10 +127,10 @@ static int SDLCALL adder(void *junk)
static void runAdder(void) static void runAdder(void)
{ {
Uint32 start, end; Uint64 start, end;
int T = NThreads; int T = NThreads;
start = SDL_GetTicks(); start = SDL_GetTicksNS();
threadDone = SDL_CreateSemaphore(0); threadDone = SDL_CreateSemaphore(0);
@ -146,9 +146,9 @@ static void runAdder(void)
SDL_DestroySemaphore(threadDone); SDL_DestroySemaphore(threadDone);
end = SDL_GetTicks(); end = SDL_GetTicksNS();
SDL_Log("Finished in %f sec\n", (end - start) / 1000.f); SDL_Log("Finished in %f sec\n", (end - start) / 1000000000.0);
} }
static void RunEpicTest() static void RunEpicTest()
@ -585,7 +585,7 @@ static void RunFIFOTest(SDL_bool lock_free)
SDL_Thread *fifo_thread = NULL; SDL_Thread *fifo_thread = NULL;
WriterData writerData[NUM_WRITERS]; WriterData writerData[NUM_WRITERS];
ReaderData readerData[NUM_READERS]; ReaderData readerData[NUM_READERS];
Uint32 start, end; Uint64 start, end;
int i, j; int i, j;
int grand_total; int grand_total;
char textBuffer[1024]; char textBuffer[1024];
@ -601,7 +601,7 @@ static void RunFIFOTest(SDL_bool lock_free)
queue.mutex = SDL_CreateMutex(); queue.mutex = SDL_CreateMutex();
} }
start = SDL_GetTicks(); start = SDL_GetTicksNS();
#ifdef TEST_SPINLOCK_FIFO #ifdef TEST_SPINLOCK_FIFO
/* Start a monitoring thread */ /* Start a monitoring thread */
@ -646,7 +646,7 @@ static void RunFIFOTest(SDL_bool lock_free)
SDL_WaitThread(readerData[i].thread, NULL); SDL_WaitThread(readerData[i].thread, NULL);
} }
end = SDL_GetTicks(); end = SDL_GetTicksNS();
/* Wait for the FIFO thread */ /* Wait for the FIFO thread */
if (fifo_thread) { if (fifo_thread) {
@ -657,7 +657,7 @@ static void RunFIFOTest(SDL_bool lock_free)
SDL_DestroyMutex(queue.mutex); SDL_DestroyMutex(queue.mutex);
} }
SDL_Log("Finished in %f sec\n", (end - start) / 1000.f); SDL_Log("Finished in %f sec\n", (end - start) / 1000000000.0);
SDL_Log("\n"); SDL_Log("\n");
for (i = 0; i < NUM_WRITERS; ++i) { for (i = 0; i < NUM_WRITERS; ++i) {

View File

@ -61,11 +61,11 @@ int timer_getPerformanceFrequency(void *arg)
*/ */
int timer_delayAndGetTicks(void *arg) int timer_delayAndGetTicks(void *arg)
{ {
const Uint32 testDelay = 100; const int testDelay = 100;
const Uint32 marginOfError = 25; const int marginOfError = 25;
Uint32 result; Uint64 result;
Uint32 result2; Uint64 result2;
Uint32 difference; Sint64 difference;
/* Zero delay */ /* Zero delay */
SDL_Delay(0); SDL_Delay(0);
@ -81,17 +81,17 @@ int timer_delayAndGetTicks(void *arg)
/* Get ticks count - should be non-zero by now */ /* Get ticks count - should be non-zero by now */
result = SDL_GetTicks(); result = SDL_GetTicks();
SDLTest_AssertPass("Call to SDL_GetTicks()"); SDLTest_AssertPass("Call to SDL_GetTicks()");
SDLTest_AssertCheck(result > 0, "Check result value, expected: >0, got: %" SDL_PRIu32, result); SDLTest_AssertCheck(result > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result);
/* Delay a bit longer and measure ticks and verify difference */ /* Delay a bit longer and measure ticks and verify difference */
SDL_Delay(testDelay); SDL_Delay(testDelay);
SDLTest_AssertPass("Call to SDL_Delay(%" SDL_PRIu32 ")", testDelay); SDLTest_AssertPass("Call to SDL_Delay(%d)", testDelay);
result2 = SDL_GetTicks(); result2 = SDL_GetTicks();
SDLTest_AssertPass("Call to SDL_GetTicks()"); SDLTest_AssertPass("Call to SDL_GetTicks()");
SDLTest_AssertCheck(result2 > 0, "Check result value, expected: >0, got: %" SDL_PRIu32, result2); SDLTest_AssertCheck(result2 > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result2);
difference = result2 - result; difference = result2 - result;
SDLTest_AssertCheck(difference > (testDelay - marginOfError), "Check difference, expected: >%" SDL_PRIu32 ", got: %" SDL_PRIu32, testDelay - marginOfError, difference); SDLTest_AssertCheck(difference > (testDelay - marginOfError), "Check difference, expected: >%d, got: %" SDL_PRIu64, testDelay - marginOfError, difference);
SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%" SDL_PRIu32 ", got: %" SDL_PRIu32, testDelay + marginOfError, difference); SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%d, got: %" SDL_PRIu64, testDelay + marginOfError, difference);
return TEST_COMPLETED; return TEST_COMPLETED;
} }

View File

@ -31,8 +31,9 @@ static int cycle_direction = 1;
static int current_alpha = 255; static int current_alpha = 255;
static int current_color = 255; static int current_color = 255;
static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE; static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
static Uint32 next_fps_check, frames; static Uint64 next_fps_check;
static const Uint32 fps_check_delay = 5000; static Uint32 frames;
static const int fps_check_delay = 5000;
int done; int done;
@ -175,7 +176,7 @@ void DrawRects(SDL_Renderer *renderer)
void loop() void loop()
{ {
Uint32 now; Uint64 now;
int i; int i;
SDL_Event event; SDL_Event event;
@ -204,9 +205,9 @@ void loop()
#endif #endif
frames++; frames++;
now = SDL_GetTicks(); now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, next_fps_check)) { if (now >= next_fps_check) {
/* Print out some timing information */ /* Print out some timing information */
const Uint32 then = next_fps_check - fps_check_delay; const Uint64 then = next_fps_check - fps_check_delay;
const double fps = ((double)frames * 1000) / (now - then); const double fps = ((double)frames * 1000) / (now - then);
SDL_Log("%2.2f frames per second\n", fps); SDL_Log("%2.2f frames per second\n", fps);
next_fps_check = now + fps_check_delay; next_fps_check = now + fps_check_delay;

View File

@ -164,7 +164,8 @@ int main(int argc, char *argv[])
{ {
int i; int i;
const char *icon = "icon.bmp"; const char *icon = "icon.bmp";
Uint32 then, now, frames; Uint64 then, now;
Uint32 frames;
/* Enable standard application logging */ /* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

View File

@ -203,7 +203,8 @@ int main(int argc, char *argv[])
int i, done; int i, done;
SDL_DisplayMode mode; SDL_DisplayMode mode;
SDL_Event event; SDL_Event event;
Uint32 then, now, frames; Uint64 then, now;
Uint32 frames;
int status; int status;
int dw, dh; int dw, dh;
int swap_interval = 0; int swap_interval = 0;

View File

@ -615,7 +615,7 @@ int main(int argc, char *argv[])
int value; int value;
int i; int i;
SDL_DisplayMode mode; SDL_DisplayMode mode;
Uint32 then, now; Uint64 then, now;
int status; int status;
shader_data *data; shader_data *data;

View File

@ -434,7 +434,7 @@ int main(int argc, char *argv[])
int value; int value;
int i; int i;
SDL_DisplayMode mode; SDL_DisplayMode mode;
Uint32 then, now; Uint64 then, now;
int status; int status;
shader_data *data; shader_data *data;
char *path = NULL; char *path = NULL;

View File

@ -278,7 +278,8 @@ void loop()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i; int i;
Uint32 then, now, frames; Uint64 then, now;
Uint32 frames;
/* Enable standard application logging */ /* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

View File

@ -93,7 +93,8 @@ void loop()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
Uint32 then, now, frames; Uint64 then, now;
Uint32 frames;
#endif #endif
/* Enable standard application logging */ /* Enable standard application logging */

View File

@ -112,7 +112,7 @@ int main(int argc, char *argv[])
{ {
int i; int i;
int frames; int frames;
Uint32 then, now; Uint64 then, now;
/* Enable standard application logging */ /* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

View File

@ -205,7 +205,7 @@ int main(int argc, char *argv[])
{ {
int i; int i;
int frames; int frames;
Uint32 then, now; Uint64 then, now;
/* Enable standard application logging */ /* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

View File

@ -102,7 +102,7 @@ int main(int argc, char *argv[])
{ {
int i; int i;
int frames; int frames;
Uint32 then, now; Uint64 then, now;
/* Enable standard application logging */ /* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

View File

@ -98,9 +98,9 @@ TestRealWorld(int init_sem)
static void static void
TestWaitTimeout(void) TestWaitTimeout(void)
{ {
Uint32 start_ticks; Uint64 start_ticks;
Uint32 end_ticks; Uint64 end_ticks;
Uint32 duration; Uint64 duration;
int retval; int retval;
sem = SDL_CreateSemaphore(0); sem = SDL_CreateSemaphore(0);
@ -114,7 +114,7 @@ TestWaitTimeout(void)
/* Accept a little offset in the effective wait */ /* Accept a little offset in the effective wait */
SDL_assert(duration > 1900 && duration < 2050); SDL_assert(duration > 1900 && duration < 2050);
SDL_Log("Wait took %" SDL_PRIu32 " milliseconds\n\n", duration); SDL_Log("Wait took %" SDL_PRIu64 " milliseconds\n\n", duration);
/* Check to make sure the return value indicates timed out */ /* Check to make sure the return value indicates timed out */
if (retval != SDL_MUTEX_TIMEDOUT) { if (retval != SDL_MUTEX_TIMEDOUT) {
@ -127,9 +127,9 @@ TestWaitTimeout(void)
static void static void
TestOverheadUncontended(void) TestOverheadUncontended(void)
{ {
Uint32 start_ticks; Uint64 start_ticks;
Uint32 end_ticks; Uint64 end_ticks;
Uint32 duration; Uint64 duration;
int i, j; int i, j;
sem = SDL_CreateSemaphore(0); sem = SDL_CreateSemaphore(0);
@ -147,7 +147,7 @@ TestOverheadUncontended(void)
end_ticks = SDL_GetTicks(); end_ticks = SDL_GetTicks();
duration = end_ticks - start_ticks; duration = end_ticks - start_ticks;
SDL_Log("Took %" SDL_PRIu32 " milliseconds\n\n", duration); SDL_Log("Took %" SDL_PRIu64 " milliseconds\n\n", duration);
SDL_DestroySemaphore(sem); SDL_DestroySemaphore(sem);
} }
@ -179,9 +179,9 @@ ThreadFuncOverheadContended(void *data)
static void static void
TestOverheadContended(SDL_bool try_wait) TestOverheadContended(SDL_bool try_wait)
{ {
Uint32 start_ticks; Uint64 start_ticks;
Uint32 end_ticks; Uint64 end_ticks;
Uint32 duration; Uint64 duration;
Thread_State thread_states[NUM_THREADS] = { { 0 } }; Thread_State thread_states[NUM_THREADS] = { { 0 } };
char textBuffer[1024]; char textBuffer[1024];
int loop_count; int loop_count;
@ -223,7 +223,7 @@ TestOverheadContended(SDL_bool try_wait)
SDL_assert_release((loop_count - content_count) == NUM_OVERHEAD_OPS * NUM_OVERHEAD_OPS_MULT); SDL_assert_release((loop_count - content_count) == NUM_OVERHEAD_OPS * NUM_OVERHEAD_OPS_MULT);
duration = end_ticks - start_ticks; duration = end_ticks - start_ticks;
SDL_Log("Took %" SDL_PRIu32 " milliseconds, threads %s %d out of %d times in total (%.2f%%)\n", SDL_Log("Took %" SDL_PRIu64 " milliseconds, threads %s %d out of %d times in total (%.2f%%)\n",
duration, try_wait ? "where contended" : "timed out", content_count, duration, try_wait ? "where contended" : "timed out", content_count,
loop_count, ((float)content_count * 100) / loop_count); loop_count, ((float)content_count * 100) / loop_count);
/* Print how many semaphores where consumed per thread */ /* Print how many semaphores where consumed per thread */

View File

@ -37,8 +37,9 @@ static SDL_Rect *positions;
static SDL_Rect *velocities; static SDL_Rect *velocities;
static int sprite_w, sprite_h; static int sprite_w, sprite_h;
static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND; static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND;
static Uint32 next_fps_check, frames; static Uint64 next_fps_check;
static const Uint32 fps_check_delay = 5000; static Uint32 frames;
static const int fps_check_delay = 5000;
static int use_rendergeometry = 0; static int use_rendergeometry = 0;
/* Number of iterations to move sprites - used for visual tests. */ /* Number of iterations to move sprites - used for visual tests. */
@ -393,7 +394,7 @@ void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
void loop() void loop()
{ {
Uint32 now; Uint64 now;
int i; int i;
SDL_Event event; SDL_Event event;
@ -415,9 +416,9 @@ void loop()
frames++; frames++;
now = SDL_GetTicks(); now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, next_fps_check)) { if (now >= next_fps_check) {
/* Print out some timing information */ /* Print out some timing information */
const Uint32 then = next_fps_check - fps_check_delay; const Uint64 then = next_fps_check - fps_check_delay;
const double fps = ((double)frames * 1000) / (now - then); const double fps = ((double)frames * 1000) / (now - then);
SDL_Log("%2.2f frames per second\n", fps); SDL_Log("%2.2f frames per second\n", fps);
next_fps_check = now + fps_check_delay; next_fps_check = now + fps_check_delay;

View File

@ -37,9 +37,8 @@ int main(int argc, char *argv[])
{ {
int i, desired; int i, desired;
SDL_TimerID t1, t2, t3; SDL_TimerID t1, t2, t3;
Uint64 start64, now64;
Uint32 start32, now32;
Uint64 start, now; Uint64 start, now;
Uint64 start_perf, now_perf;
/* Enable standard application logging */ /* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
@ -58,13 +57,11 @@ int main(int argc, char *argv[])
/* Verify SDL_GetTicks* acts monotonically increasing, and not erratic. */ /* Verify SDL_GetTicks* acts monotonically increasing, and not erratic. */
SDL_Log("Sanity-checking GetTicks\n"); SDL_Log("Sanity-checking GetTicks\n");
for (i = 0; i < 1000; ++i) { for (i = 0; i < 1000; ++i) {
start64 = SDL_GetTicks64(); start = SDL_GetTicks();
start32 = SDL_GetTicks();
SDL_Delay(1); SDL_Delay(1);
now64 = SDL_GetTicks64() - start64; now = SDL_GetTicks() - start;
now32 = SDL_GetTicks() - start32; if (now > 100) {
if (now32 > 100 || now64 > 100) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "testtimer.c: Delta time erratic at iter %d. Delay 1ms = %d ms in ticks\n", i, (int)now);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "testtimer.c: Delta time erratic at iter %d. Delay 1ms = %d ms in ticks, %d ms in ticks64\n", i, (int)now32, (int)now64);
SDL_Quit(); SDL_Quit();
return 1; return 1;
} }
@ -120,22 +117,20 @@ int main(int argc, char *argv[])
SDL_RemoveTimer(t2); SDL_RemoveTimer(t2);
SDL_RemoveTimer(t3); SDL_RemoveTimer(t3);
start = SDL_GetPerformanceCounter(); start_perf = SDL_GetPerformanceCounter();
for (i = 0; i < 1000000; ++i) { for (i = 0; i < 1000000; ++i) {
ticktock(0, NULL); ticktock(0, NULL);
} }
now = SDL_GetPerformanceCounter(); now_perf = SDL_GetPerformanceCounter();
SDL_Log("1 million iterations of ticktock took %f ms\n", (double)((now - start) * 1000) / SDL_GetPerformanceFrequency()); SDL_Log("1 million iterations of ticktock took %f ms\n", (double)((now_perf - start_perf) * 1000) / SDL_GetPerformanceFrequency());
SDL_Log("Performance counter frequency: %" SDL_PRIu64 "\n", SDL_GetPerformanceFrequency()); SDL_Log("Performance counter frequency: %" SDL_PRIu64 "\n", SDL_GetPerformanceFrequency());
start64 = SDL_GetTicks64(); start = SDL_GetTicks();
start32 = SDL_GetTicks(); start_perf = SDL_GetPerformanceCounter();
start = SDL_GetPerformanceCounter();
SDL_Delay(1000); SDL_Delay(1000);
now = SDL_GetPerformanceCounter(); now_perf = SDL_GetPerformanceCounter();
now64 = SDL_GetTicks64(); now = SDL_GetTicks();
now32 = SDL_GetTicks(); SDL_Log("Delay 1 second = %d ms in ticks, %f ms according to performance counter\n", (int)(now - start), (double)((now_perf - start_perf) * 1000) / SDL_GetPerformanceFrequency());
SDL_Log("Delay 1 second = %d ms in ticks, %d ms in ticks64, %f ms according to performance counter\n", (int)(now32 - start32), (int)(now64 - start64), (double)((now - start) * 1000) / SDL_GetPerformanceFrequency());
SDL_Quit(); SDL_Quit();
return 0; return 0;

View File

@ -146,7 +146,8 @@ void loop()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i; int i;
Uint32 then, now, frames; Uint64 then, now;
Uint32 frames;
/* Initialize test framework */ /* Initialize test framework */
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);

View File

@ -1081,7 +1081,8 @@ int main(int argc, char **argv)
int done; int done;
SDL_DisplayMode mode; SDL_DisplayMode mode;
SDL_Event event; SDL_Event event;
Uint32 then, now, frames; Uint64 then, now;
Uint32 frames;
int dw, dh; int dw, dh;
/* Enable standard application logging */ /* Enable standard application logging */

View File

@ -254,7 +254,8 @@ int main(int argc, char **argv)
int current = 0; int current = 0;
int pitch; int pitch;
Uint8 *raw_yuv; Uint8 *raw_yuv;
Uint32 then, now, i, iterations = 100; Uint64 then, now;
Uint32 i, iterations = 100;
SDL_bool should_run_automated_tests = SDL_FALSE; SDL_bool should_run_automated_tests = SDL_FALSE;
while (argv[arg] && *argv[arg] == '-') { while (argv[arg] && *argv[arg] == '-') {
@ -345,7 +346,7 @@ int main(int argc, char **argv)
SDL_ConvertPixels(original->w, original->h, yuv_format, raw_yuv, pitch, rgb_format, converted->pixels, converted->pitch); SDL_ConvertPixels(original->w, original->h, yuv_format, raw_yuv, pitch, rgb_format, converted->pixels, converted->pitch);
} }
now = SDL_GetTicks(); now = SDL_GetTicks();
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%" SDL_PRIu32 " iterations in %" SDL_PRIu32 " ms, %.2fms each\n", iterations, (now - then), (float)(now - then) / iterations); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%" SDL_PRIu32 " iterations in %" SDL_PRIu64 " ms, %.2fms each\n", iterations, (now - then), (float)(now - then) / iterations);
window = SDL_CreateWindow("YUV test", window = SDL_CreateWindow("YUV test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,