From 8121bbd083b5a568709305270b554f2add3ba4a1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 2 Dec 2022 01:17:17 -0800 Subject: [PATCH] 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 --- WhatsNew.txt | 8 +- docs/README-migration.md | 28 +++++ include/SDL3/SDL_events.h | 109 +++++++++++------ include/SDL3/SDL_mutex.h | 97 ++++++++++++--- include/SDL3/SDL_timer.h | 86 +++++-------- src/audio/alsa/SDL_alsa_audio.c | 4 +- src/core/unix/SDL_poll.c | 17 ++- src/core/unix/SDL_poll.h | 2 +- src/dynapi/SDL_dynapi_overrides.h | 6 +- src/dynapi/SDL_dynapi_procs.h | 14 ++- src/events/SDL_events.c | 64 ++++++---- src/events/SDL_mouse.c | 4 +- src/events/SDL_mouse_c.h | 2 +- src/haptic/android/SDL_syshaptic.c | 11 +- src/haptic/windows/SDL_windowshaptic_c.h | 2 +- src/haptic/windows/SDL_xinputhaptic.c | 5 +- src/hidapi/SDL_hidapi.c | 6 +- src/joystick/SDL_gamecontroller.c | 6 +- src/joystick/SDL_joystick.c | 22 +--- src/joystick/SDL_sysjoystick.h | 8 +- src/joystick/android/SDL_sysjoystick.c | 7 +- src/joystick/hidapi/SDL_hidapi_ps4.c | 8 +- src/joystick/hidapi/SDL_hidapi_ps5.c | 8 +- src/joystick/hidapi/SDL_hidapi_shield.c | 8 +- src/joystick/hidapi/SDL_hidapi_switch.c | 82 ++++++------- src/joystick/hidapi/SDL_hidapi_wii.c | 36 +++--- src/joystick/hidapi/SDL_hidapi_xboxone.c | 14 +-- src/joystick/linux/SDL_sysjoystick.c | 6 +- src/joystick/windows/SDL_rawinputjoystick.c | 6 +- src/power/uikit/SDL_syspower.m | 4 +- src/render/SDL_render.c | 18 +-- src/render/SDL_sysrender.h | 4 +- src/thread/SDL_thread.c | 39 ++++++ src/thread/generic/SDL_syscond.c | 19 +-- src/thread/generic/SDL_syscond_c.h | 4 +- src/thread/generic/SDL_syssem.c | 55 +++------ src/thread/n3ds/SDL_syscond.c | 15 +-- src/thread/n3ds/SDL_syssem.c | 21 +--- src/thread/ngage/SDL_syssem.cpp | 33 ++--- src/thread/ps2/SDL_syssem.c | 18 +-- src/thread/psp/SDL_syscond.c | 16 +-- src/thread/psp/SDL_syssem.c | 25 ++-- src/thread/pthread/SDL_syscond.c | 32 ++--- src/thread/pthread/SDL_syssem.c | 74 +++++------- src/thread/stdcpp/SDL_syscond.cpp | 17 +-- src/thread/vita/SDL_syscond.c | 16 +-- src/thread/vita/SDL_syssem.c | 25 ++-- src/thread/windows/SDL_syscond_cv.c | 32 ++--- src/thread/windows/SDL_syssem.c | 119 ++++++------------ src/timer/SDL_timer.c | 127 ++++++++++++++++---- src/timer/dummy/SDL_systimer.c | 31 +---- src/timer/haiku/SDL_systimer.c | 34 +----- src/timer/n3ds/SDL_systimer.c | 35 +----- src/timer/ngage/SDL_systimer.cpp | 48 ++------ src/timer/ps2/SDL_systimer.c | 42 +------ src/timer/psp/SDL_systimer.c | 51 +++----- src/timer/unix/SDL_systimer.c | 104 +++++----------- src/timer/vita/SDL_systimer.c | 42 +------ src/timer/windows/SDL_systimer.c | 122 +++---------------- src/video/SDL_sysvideo.h | 2 +- src/video/cocoa/SDL_cocoaevents.h | 2 +- src/video/cocoa/SDL_cocoaevents.m | 8 +- src/video/cocoa/SDL_cocoaopengl.m | 2 +- src/video/cocoa/SDL_cocoawindow.m | 6 +- src/video/wayland/SDL_waylanddatamanager.c | 6 +- src/video/wayland/SDL_waylandevents.c | 16 +-- src/video/wayland/SDL_waylandevents_c.h | 4 +- src/video/wayland/SDL_waylandopengles.c | 8 +- src/video/windows/SDL_windowsevents.c | 17 +-- src/video/windows/SDL_windowsevents.h | 2 +- src/video/windows/SDL_windowswindow.h | 2 +- src/video/x11/SDL_x11clipboard.c | 4 +- src/video/x11/SDL_x11events.c | 21 ++-- src/video/x11/SDL_x11events.h | 2 +- src/video/x11/SDL_x11video.h | 4 +- src/video/x11/SDL_x11window.c | 19 ++- src/video/x11/SDL_x11window.h | 6 +- test/controllermap.c | 6 +- test/testatomic.c | 16 +-- test/testautomation_timer.c | 20 +-- test/testdraw2.c | 11 +- test/testgeometry.c | 3 +- test/testgl2.c | 3 +- test/testgles2.c | 2 +- test/testgles2_sdf.c | 2 +- test/testintersections.c | 3 +- test/testoffscreen.c | 3 +- test/testrendercopyex.c | 2 +- test/testrendertarget.c | 2 +- test/testscale.c | 2 +- test/testsem.c | 24 ++-- test/testsprite2.c | 11 +- test/testtimer.c | 31 ++--- test/testviewport.c | 3 +- test/testvulkan.c | 3 +- test/testyuv.c | 5 +- 96 files changed, 938 insertions(+), 1243 deletions(-) diff --git a/WhatsNew.txt b/WhatsNew.txt index a0d065cc5..c9b3bfb87 100644 --- a/WhatsNew.txt +++ b/WhatsNew.txt @@ -32,4 +32,10 @@ General: * Added SDL_CreateSurface() and SDL_CreateSurfaceFrom() which replace the SDL_CreateRGBSurface*() * Removed unused 'flags' parameter from SDL_ConvertSurface and SDL_ConvertSurfaceFormat * 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() diff --git a/docs/README-migration.md b/docs/README-migration.md index 735d7c682..079d22fe1 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -31,6 +31,10 @@ LDFLAGS += $(shell pkg-config sdl3 --libs) 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 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. +## 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_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0 diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 0e110fdfe..00c111006 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -182,7 +182,7 @@ typedef enum typedef struct SDL_CommonEvent { Uint32 type; - Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ } SDL_CommonEvent; /** @@ -191,7 +191,7 @@ typedef struct SDL_CommonEvent typedef struct 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 */ Uint8 event; /**< ::SDL_DisplayEventID */ Uint8 padding1; @@ -206,7 +206,7 @@ typedef struct SDL_DisplayEvent typedef struct 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 */ Uint8 event; /**< ::SDL_WindowEventID */ Uint8 padding1; @@ -222,7 +222,7 @@ typedef struct SDL_WindowEvent typedef struct SDL_KeyboardEvent { 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 */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 repeat; /**< Non-zero if this is a key repeat */ @@ -238,7 +238,7 @@ typedef struct SDL_KeyboardEvent typedef struct SDL_TextEditingEvent { 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 */ char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */ Sint32 start; /**< The start cursor of selected editing text */ @@ -252,7 +252,7 @@ typedef struct SDL_TextEditingEvent typedef struct SDL_TextEditingExtEvent { 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 */ 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 */ @@ -266,7 +266,7 @@ typedef struct SDL_TextEditingExtEvent typedef struct SDL_TextInputEvent { 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 */ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ } SDL_TextInputEvent; @@ -277,7 +277,7 @@ typedef struct SDL_TextInputEvent typedef struct SDL_MouseMotionEvent { 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 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint32 state; /**< The current button state */ @@ -293,7 +293,7 @@ typedef struct SDL_MouseMotionEvent typedef struct SDL_MouseButtonEvent { 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 */ SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint8 button; /**< The mouse button index */ @@ -310,7 +310,7 @@ typedef struct SDL_MouseButtonEvent typedef struct SDL_MouseWheelEvent { 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 */ 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 */ @@ -328,7 +328,7 @@ typedef struct SDL_MouseWheelEvent typedef struct SDL_JoyAxisEvent { 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 */ Uint8 axis; /**< The joystick axis index */ Uint8 padding1; @@ -344,7 +344,7 @@ typedef struct SDL_JoyAxisEvent typedef struct SDL_JoyBallEvent { 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 */ Uint8 ball; /**< The joystick trackball index */ Uint8 padding1; @@ -360,7 +360,7 @@ typedef struct SDL_JoyBallEvent typedef struct SDL_JoyHatEvent { 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 */ Uint8 hat; /**< The joystick hat index */ Uint8 value; /**< The hat position value. @@ -380,7 +380,7 @@ typedef struct SDL_JoyHatEvent typedef struct SDL_JoyButtonEvent { 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 */ Uint8 button; /**< The joystick button index */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ @@ -394,7 +394,7 @@ typedef struct SDL_JoyButtonEvent typedef struct SDL_JoyDeviceEvent { 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_JoyDeviceEvent; @@ -404,7 +404,7 @@ typedef struct SDL_JoyDeviceEvent typedef struct SDL_JoyBatteryEvent { 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_JoystickPowerLevel level; /**< The joystick battery level */ } SDL_JoyBatteryEvent; @@ -415,7 +415,7 @@ typedef struct SDL_JoyBatteryEvent typedef struct SDL_ControllerAxisEvent { 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 */ Uint8 axis; /**< The controller axis (SDL_GameControllerAxis) */ Uint8 padding1; @@ -432,7 +432,7 @@ typedef struct SDL_ControllerAxisEvent typedef struct SDL_ControllerButtonEvent { 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 */ Uint8 button; /**< The controller button (SDL_GameControllerButton) */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ @@ -447,7 +447,7 @@ typedef struct SDL_ControllerButtonEvent typedef struct SDL_ControllerDeviceEvent { 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_ControllerDeviceEvent; @@ -457,7 +457,7 @@ typedef struct SDL_ControllerDeviceEvent typedef struct SDL_ControllerTouchpadEvent { 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 */ Sint32 touchpad; /**< The index of the touchpad */ Sint32 finger; /**< The index of the finger on the touchpad */ @@ -472,7 +472,7 @@ typedef struct SDL_ControllerTouchpadEvent typedef struct SDL_ControllerSensorEvent { 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 */ 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 */ @@ -485,7 +485,7 @@ typedef struct SDL_ControllerSensorEvent typedef struct SDL_AudioDeviceEvent { 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 */ Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */ Uint8 padding1; @@ -500,7 +500,7 @@ typedef struct SDL_AudioDeviceEvent typedef struct SDL_TouchFingerEvent { 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_FingerID fingerId; float x; /**< Normalized in the range 0...1 */ @@ -518,7 +518,7 @@ typedef struct SDL_TouchFingerEvent typedef struct SDL_MultiGestureEvent { 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 */ float dTheta; float dDist; @@ -535,7 +535,7 @@ typedef struct SDL_MultiGestureEvent typedef struct SDL_DollarGestureEvent { 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_GestureID gestureId; Uint32 numFingers; @@ -553,7 +553,7 @@ typedef struct SDL_DollarGestureEvent typedef struct SDL_DropEvent { 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 */ Uint32 windowID; /**< The window that was dropped on, if any */ } SDL_DropEvent; @@ -565,7 +565,7 @@ typedef struct SDL_DropEvent typedef struct SDL_SensorEvent { 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 */ 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. */ @@ -577,7 +577,7 @@ typedef struct SDL_SensorEvent typedef struct SDL_QuitEvent { Uint32 type; /**< ::SDL_QUIT */ - Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ } SDL_QuitEvent; /** @@ -586,7 +586,7 @@ typedef struct SDL_QuitEvent typedef struct SDL_OSEvent { Uint32 type; /**< ::SDL_QUIT */ - Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ } SDL_OSEvent; /** @@ -595,7 +595,7 @@ typedef struct SDL_OSEvent typedef struct SDL_UserEvent { 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 */ Sint32 code; /**< User defined event code */ void *data1; /**< User defined data pointer */ @@ -615,7 +615,7 @@ typedef struct SDL_SysWMmsg SDL_SysWMmsg; typedef struct 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_SysWMEvent; @@ -669,7 +669,7 @@ typedef union SDL_Event 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. */ - Uint8 padding[sizeof(void *) <= 8 ? 56 : sizeof(void *) == 16 ? 64 : 3 * sizeof(void *)]; + Uint8 padding[128]; } SDL_Event; /* 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_WaitEvent * \sa SDL_WaitEventTimeout + * \sa SDL_WaitEventTimeoutNS */ 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_PumpEvents * \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 @@ -914,10 +916,13 @@ extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * 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 timeout the maximum number of milliseconds to wait for the next - * available event + * \param timeoutMS the maximum number of milliseconds 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. @@ -927,9 +932,39 @@ extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event); * \sa SDL_PollEvent * \sa SDL_PumpEvents * \sa SDL_WaitEvent + * \sa SDL_WaitEventTimeoutNS */ -extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event * event, - int timeout); +extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS); + +/** + * 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. diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index 6fdbd7db9..7495ab4c1 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -46,7 +46,7 @@ extern "C" { /** * 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_SemWait * \sa SDL_SemWaitTimeout + * \sa SDL_SemWaitTimeoutNS */ 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_SemWait * \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. @@ -240,8 +242,9 @@ extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem * sem); * \sa SDL_SemValue * \sa SDL_SemWait * \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. @@ -264,8 +267,9 @@ extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem * sem); * \sa SDL_SemValue * \sa SDL_SemWait * \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. @@ -276,7 +280,7 @@ extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem); * successful it will atomically decrement the semaphore value. * * \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 * succeed in the allotted time, or a negative error code on failure; * call SDL_GetError() for more information. @@ -289,8 +293,35 @@ extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem); * \sa SDL_SemTryWait * \sa SDL_SemValue * \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. @@ -308,7 +339,7 @@ extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout); * \sa SDL_SemWait * \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. @@ -320,7 +351,7 @@ extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem); * * \sa SDL_CreateSemaphore */ -extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem * sem); +extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem); /* @} *//* Semaphore functions */ @@ -346,6 +377,7 @@ typedef struct SDL_cond SDL_cond; * \sa SDL_CondSignal * \sa SDL_CondWait * \sa SDL_CondWaitTimeout + * \sa SDL_CondWaitTimeoutNS * \sa SDL_DestroyCond */ 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_CondWait * \sa SDL_CondWaitTimeout + * \sa SDL_CondWaitTimeoutNS * \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. @@ -377,10 +410,11 @@ extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond); * \sa SDL_CondBroadcast * \sa SDL_CondWait * \sa SDL_CondWaitTimeout + * \sa SDL_CondWaitTimeoutNS * \sa SDL_CreateCond * \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. @@ -394,10 +428,11 @@ extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond); * \sa SDL_CondSignal * \sa SDL_CondWait * \sa SDL_CondWaitTimeout + * \sa SDL_CondWaitTimeoutNS * \sa SDL_CreateCond * \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. @@ -422,10 +457,11 @@ extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond); * \sa SDL_CondBroadcast * \sa SDL_CondSignal * \sa SDL_CondWaitTimeout + * \sa SDL_CondWaitTimeoutNS * \sa SDL_CreateCond * \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. @@ -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 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 * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if * 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_CondSignal * \sa SDL_CondWait + * \sa SDL_CondWaitTimeoutNS * \sa SDL_CreateCond * \sa SDL_DestroyCond */ -extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond, - SDL_mutex * mutex, Uint32 ms); +extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, + 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 */ diff --git a/include/SDL3/SDL_timer.h b/include/SDL3/SDL_timer.h index 66fb8538b..01f83a88a 100644 --- a/include/SDL3/SDL_timer.h +++ b/include/SDL3/SDL_timer.h @@ -38,72 +38,37 @@ extern "C" { #endif /** - * Get the number of milliseconds since SDL library initialization. - * - * 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 + * SDL time constants */ -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. * - * 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 * since the SDL library initialized. * * \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 - * attempts to deal with the 32-bit counter wrapping back to zero every ~49 - * days, but should _not_ be used with SDL_GetTicks64(), which does not have - * that problem. + * \returns an unsigned 64-bit value representing the number of nanoseconds + * since the SDL library initialized. * - * For example, with SDL_GetTicks(), if you want to wait 100 ms, you could - * 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). + * \since This function is available since SDL 3.0.0. */ -#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. @@ -146,15 +111,28 @@ extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void); */ 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. * * 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 * 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. @@ -179,7 +157,7 @@ typedef int SDL_TimerID; * iteration. * * 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. * * \param interval the timer delay, in milliseconds, passed to `callback` diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 99d691260..327aa6d5b 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -909,8 +909,8 @@ static int SDLCALL ALSA_HotplugThread(void *arg) while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) { /* Block awhile before checking again, unless we're told to stop. */ - const Uint32 ticks = SDL_GetTicks() + 5000; - while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && !SDL_TICKS_PASSED(SDL_GetTicks(), ticks)) { + const Uint64 ticks = SDL_GetTicks() + 5000; + while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && SDL_GetTicks() < ticks) { SDL_Delay(100); } diff --git a/src/core/unix/SDL_poll.c b/src/core/unix/SDL_poll.c index 60fdefeba..bf3a4f5ea 100644 --- a/src/core/unix/SDL_poll.c +++ b/src/core/unix/SDL_poll.c @@ -32,7 +32,7 @@ #endif #include -int SDL_IOReady(int fd, int flags, int timeoutMS) +int SDL_IOReady(int fd, int flags, Sint64 timeoutNS) { int result; @@ -42,6 +42,7 @@ int SDL_IOReady(int fd, int flags, int timeoutMS) do { #ifdef HAVE_POLL struct pollfd info; + int timeoutMS; info.fd = fd; info.events = 0; @@ -51,6 +52,14 @@ int SDL_IOReady(int fd, int flags, int timeoutMS) if (flags & SDL_IOR_WRITE) { 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); #else fd_set rfdset, *rfdp = NULL; @@ -71,9 +80,9 @@ int SDL_IOReady(int fd, int flags, int timeoutMS) wfdp = &wfdset; } - if (timeoutMS >= 0) { - tv.tv_sec = timeoutMS / 1000; - tv.tv_usec = (timeoutMS % 1000) * 1000; + if (timeoutNS >= 0) { + tv.tv_sec = (timeoutNS / SDL_NS_PER_SECOND); + tv.tv_usec = SDL_NS_TO_US(timeoutNS % SDL_NS_PER_SECOND); tvp = &tv; } diff --git a/src/core/unix/SDL_poll.h b/src/core/unix/SDL_poll.h index a5ec7c40e..f511557b3 100644 --- a/src/core/unix/SDL_poll.h +++ b/src/core/unix/SDL_poll.h @@ -28,7 +28,7 @@ #define SDL_IOR_WRITE 0x2 #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_ */ diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index a021787a6..dc085600a 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -809,7 +809,6 @@ #define SDL_asprintf SDL_asprintf_REAL #define SDL_vasprintf SDL_vasprintf_REAL #define SDL_GetWindowICCProfile SDL_GetWindowICCProfile_REAL -#define SDL_GetTicks64 SDL_GetTicks64_REAL #define SDL_LinuxSetThreadPriorityAndPolicy SDL_LinuxSetThreadPriorityAndPolicy_REAL #define SDL_GameControllerGetAppleSFSymbolsNameForButton SDL_GameControllerGetAppleSFSymbolsNameForButton_REAL #define SDL_GameControllerGetAppleSFSymbolsNameForAxis SDL_GameControllerGetAppleSFSymbolsNameForAxis_REAL @@ -891,3 +890,8 @@ #define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL #define SDL_GetWindowWMInfo SDL_GetWindowWMInfo_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 diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 389c3b35d..2d4b97f13 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -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(int,SDL_PollEvent,(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(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) @@ -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(int,SDL_SemWait,(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(Uint32,SDL_SemValue,(SDL_sem *a),(a),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_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_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(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) @@ -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(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(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_GetPerformanceFrequency,(void),(),return) 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 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(Uint64,SDL_GetTicks64,(void),(),return) #ifdef __LINUX__ SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriorityAndPolicy,(Sint64 a, int b, int c),(a,b,c),return) #endif @@ -967,3 +966,8 @@ SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),) #endif 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(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),) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 53a859994..4a418a140 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -42,7 +42,7 @@ #define SDL_MAX_QUEUED_EVENTS 65535 /* 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 { @@ -963,7 +963,7 @@ void SDL_PumpEvents() int SDL_PollEvent(SDL_Event *event) { - return SDL_WaitEventTimeout(event, 0); + return SDL_WaitEventTimeoutNS(event, 0); } static SDL_bool SDL_events_need_periodic_poll() @@ -983,9 +983,9 @@ static SDL_bool SDL_events_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(); for (;;) { @@ -1021,26 +1021,26 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve return 1; } /* No events found in the queue, call WaitEventTimeout to wait for an event. */ - if (timeout > 0) { - Uint32 elapsed = SDL_GetTicks() - start; - if (elapsed >= (Uint32)timeout) { + if (timeoutNS > 0) { + Sint64 elapsed = SDL_GetTicksNS() - start; + if (elapsed >= timeoutNS) { /* Set wakeup_window to NULL without holding the lock. */ _this->wakeup_window = NULL; return 0; } - loop_timeout = (int)((Uint32)timeout - elapsed); + loop_timeoutNS = (timeoutNS - elapsed); } if (need_periodic_poll) { - if (loop_timeout >= 0) { - loop_timeout = SDL_min(loop_timeout, PERIODIC_POLL_INTERVAL_MS); + if (loop_timeoutNS >= 0) { + loop_timeoutNS = SDL_min(loop_timeoutNS, PERIODIC_POLL_INTERVAL_NS); } 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. */ _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 */ continue; } else if (status <= 0) { @@ -1086,15 +1086,27 @@ static SDL_Window *SDL_find_active_window(SDL_VideoDevice *_this) 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_Window *wakeup_window; - Uint32 start, expiration; - SDL_bool include_sentinel = (timeout == 0) ? SDL_TRUE : SDL_FALSE; + Uint64 start, expiration; + SDL_bool include_sentinel = (timeoutNS == 0) ? SDL_TRUE : SDL_FALSE; int result; /* 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 (timeout == 0) { + if (timeoutNS == 0) { /* No events available, and not willing to wait */ return 0; } @@ -1134,12 +1146,12 @@ int SDL_WaitEventTimeout(SDL_Event *event, int timeout) /* Has existing events */ return 1; } - /* We should have completely handled timeout == 0 above */ - SDL_assert(timeout != 0); + /* We should have completely handled timeoutNS == 0 above */ + SDL_assert(timeoutNS != 0); - if (timeout > 0) { - start = SDL_GetTicks(); - expiration = start + timeout; + if (timeoutNS > 0) { + start = SDL_GetTicksNS(); + expiration = start + timeoutNS; } else { start = 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. */ wakeup_window = SDL_find_active_window(_this); 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 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: return 0; case 0: - if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) { + if (timeoutNS > 0 && SDL_GetTicks() >= expiration) { /* Timeout expired and no events */ return 0; } @@ -1180,7 +1192,7 @@ int SDL_WaitEventTimeout(SDL_Event *event, int timeout) 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_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 19c90da48..05c97f9ea 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -735,9 +735,9 @@ static int SDL_PrivateSendMouseButton(SDL_Window *window, SDL_MouseID mouseID, U SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button); if (clickstate) { 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->y - clickstate->last_y) > mouse->double_click_radius) { clickstate->click_count = 0; diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 7d934be7e..b774c15bb 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -38,7 +38,7 @@ typedef struct typedef struct { int last_x, last_y; - Uint32 last_timestamp; + Uint64 last_timestamp; Uint8 click_count; } SDL_MouseClickState; diff --git a/src/haptic/android/SDL_syshaptic.c b/src/haptic/android/SDL_syshaptic.c index 25417be35..78ef23cf9 100644 --- a/src/haptic/android/SDL_syshaptic.c +++ b/src/haptic/android/SDL_syshaptic.c @@ -42,15 +42,8 @@ static int numhaptics = 0; 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; } diff --git a/src/haptic/windows/SDL_windowshaptic_c.h b/src/haptic/windows/SDL_windowshaptic_c.h index 49ad7d2ce..5dbac135b 100644 --- a/src/haptic/windows/SDL_windowshaptic_c.h +++ b/src/haptic/windows/SDL_windowshaptic_c.h @@ -46,7 +46,7 @@ struct haptic_hwdata Uint8 userid; /* XInput userid index for this joystick */ SDL_Thread *thread; SDL_mutex *mutex; - Uint32 stopTicks; + Uint64 stopTicks; SDL_atomic_t stopThread; }; diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c index 2d97311ca..42a11e778 100644 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ b/src/haptic/windows/SDL_xinputhaptic.c @@ -147,7 +147,7 @@ static int SDLCALL SDL_RunXInputHaptic(void *arg) SDL_LockMutex(hwdata->mutex); /* If we're currently running and need to stop... */ 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 }; hwdata->stopTicks = 0; 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. */ } else { 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); return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1; diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c index 99884e3b0..ad3fbc482 100644 --- a/src/hidapi/SDL_hidapi.c +++ b/src/hidapi/SDL_hidapi.c @@ -92,7 +92,7 @@ static struct SDL_bool m_bInitialized; Uint32 m_unDeviceChangeCounter; SDL_bool m_bCanGetNotifications; - Uint32 m_unLastDetect; + Uint64 m_unLastDetect; #if defined(__WIN32__) || defined(__WINGDK__) SDL_threadID m_nThreadID; @@ -367,8 +367,8 @@ HIDAPI_UpdateDiscovery() if (!SDL_HIDAPI_discovery.m_bCanGetNotifications) { const Uint32 SDL_HIDAPI_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */ - Uint32 now = SDL_GetTicks(); - if (!SDL_HIDAPI_discovery.m_unLastDetect || SDL_TICKS_PASSED(now, SDL_HIDAPI_discovery.m_unLastDetect + SDL_HIDAPI_DETECT_INTERVAL_MS)) { + Uint64 now = SDL_GetTicks(); + 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_unLastDetect = now; } diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 2bcafca78..b3bf8aa19 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -128,7 +128,7 @@ struct _SDL_GameController SDL_ExtendedGameControllerBind *bindings; SDL_ExtendedGameControllerBind **last_match_axis; Uint8 *last_hat_mask; - Uint32 guide_button_down; + Uint64 guide_button_down; 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 */ if (button == SDL_CONTROLLER_BUTTON_GUIDE) { - Uint32 now = SDL_GetTicks(); + Uint64 now = SDL_GetTicks(); if (state == SDL_PRESSED) { gamecontroller->guide_button_down = now; @@ -2910,7 +2910,7 @@ static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, S return 0; } } 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; return 0; } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index f91031eb0..ae9f0bae6 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -966,9 +966,6 @@ int SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint } else { result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble); joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS; - if (!joystick->rumble_resend) { - joystick->rumble_resend = 1; - } } 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) { joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); - if (!joystick->rumble_expiration) { - joystick->rumble_expiration = 1; - } } else { joystick->rumble_expiration = 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) { 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 { 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 || 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); joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS; } else { @@ -1665,7 +1656,7 @@ int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state) void SDL_JoystickUpdate(void) { int i; - Uint32 now; + Uint64 now; SDL_Joystick *joystick; if (!SDL_WasInit(SDL_INIT_JOYSTICK)) { @@ -1689,14 +1680,12 @@ void SDL_JoystickUpdate(void) } now = SDL_GetTicks(); - if (joystick->rumble_expiration && - SDL_TICKS_PASSED(now, joystick->rumble_expiration)) { + if (joystick->rumble_expiration && now >= joystick->rumble_expiration) { SDL_JoystickRumble(joystick, 0, 0, 0); joystick->rumble_resend = 0; } - if (joystick->rumble_resend && - SDL_TICKS_PASSED(now, joystick->rumble_resend)) { + if (joystick->rumble_resend && now >= joystick->rumble_resend) { joystick->driver->Rumble(joystick, joystick->low_frequency_rumble, joystick->high_frequency_rumble); joystick->rumble_resend = now + SDL_RUMBLE_RESEND_MS; if (joystick->rumble_resend == 0) { @@ -1704,8 +1693,7 @@ void SDL_JoystickUpdate(void) } } - if (joystick->trigger_rumble_expiration && - SDL_TICKS_PASSED(now, joystick->trigger_rumble_expiration)) { + if (joystick->trigger_rumble_expiration && now >= joystick->trigger_rumble_expiration) { SDL_JoystickRumbleTriggers(joystick, 0, 0, 0); } } diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 93cb0ea65..7bde2d77d 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -102,17 +102,17 @@ struct _SDL_Joystick Uint16 low_frequency_rumble; Uint16 high_frequency_rumble; - Uint32 rumble_expiration; - Uint32 rumble_resend; + Uint64 rumble_expiration; + Uint64 rumble_resend; Uint16 left_trigger_rumble; Uint16 right_trigger_rumble; - Uint32 trigger_rumble_expiration; + Uint64 trigger_rumble_expiration; Uint8 led_red; Uint8 led_green; Uint8 led_blue; - Uint32 led_expiration; + Uint64 led_expiration; SDL_bool attached; SDL_bool is_game_controller; diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 9e74898c8..4ae18bd77 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -494,9 +494,10 @@ static void ANDROID_JoystickDetect(void) * so we poll every three seconds * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html */ - static Uint32 timeout = 0; - if (!timeout || SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) { - timeout = SDL_GetTicks() + 3000; + static Uint64 timeout = 0; + Uint64 now = SDL_GetTicks(); + if (!timeout || now >= timeout) { + timeout = now + 3000; Android_JNI_PollInputDevices(); } } diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 8e994d1f8..728fafa38 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -137,7 +137,7 @@ typedef struct SDL_bool report_touchpad; SDL_bool hardware_calibration; IMUCalibrationData calibration[6]; - Uint32 last_packet; + Uint64 last_packet; int player_index; Uint8 rumble_left; Uint8 rumble_right; @@ -1037,7 +1037,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) Uint8 data[USB_PACKET_LENGTH * 2]; int size; int packet_count = 0; - Uint32 now = SDL_GetTicks(); + Uint64 now = SDL_GetTicks(); if (device->num_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 (packet_count == 0) { /* 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 */ HIDAPI_DriverPS4_TickleBluetooth(device); } @@ -1106,7 +1106,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) if (packet_count == 0) { if (device->num_joysticks > 0) { /* 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]); } } diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index b8ca93623..e06b2781e 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -215,7 +215,7 @@ typedef struct SDL_bool hardware_calibration; IMUCalibrationData calibration[6]; Uint16 firmware_version; - Uint32 last_packet; + Uint64 last_packet; int player_index; SDL_bool player_lights; Uint8 rumble_left; @@ -703,7 +703,7 @@ static void HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device) packet->rgucSensorTimestamp[1], packet->rgucSensorTimestamp[2], packet->rgucSensorTimestamp[3]); - if (SDL_TICKS_PASSED(timestamp, connection_complete)) { + if ((Sint32)(connection_complete - timestamp) <= 0) { led_reset_complete = SDL_TRUE; } } else { @@ -1305,7 +1305,7 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) Uint8 data[USB_PACKET_LENGTH * 2]; int size; int packet_count = 0; - Uint32 now = SDL_GetTicks(); + Uint64 now = SDL_GetTicks(); if (device->num_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 (packet_count == 0) { /* 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 */ HIDAPI_DriverPS5_TickleBluetooth(device); } diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 724de2423..c2666e31b 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -78,13 +78,13 @@ typedef struct SDL_JoystickPowerLevel battery_level; SDL_bool charging; - Uint32 last_battery_query_time; + Uint64 last_battery_query_time; SDL_bool rumble_report_pending; SDL_bool rumble_update_pending; Uint8 left_motor_amplitude; Uint8 right_motor_amplitude; - Uint32 last_rumble_time; + Uint64 last_rumble_time; Uint8 last_state[USB_PACKET_LENGTH]; } 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 */ - 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(); HIDAPI_DriverShield_SendCommand(device, CMD_BATTERY_STATE, NULL, 0); } /* Retransmit rumble packets if they've lasted longer than the hardware supports */ 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; HIDAPI_DriverShield_SendNextRumble(device); } diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 8006440d3..fd9b6176b 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -254,18 +254,18 @@ typedef struct SwitchCommonOutputPacket_t m_RumblePacket; Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength]; SDL_bool m_bRumbleActive; - Uint32 m_unRumbleSent; + Uint64 m_ulRumbleSent; SDL_bool m_bRumblePending; SDL_bool m_bRumbleZeroPending; Uint32 m_unRumblePending; SDL_bool m_bReportSensors; SDL_bool m_bHasSensorData; - Uint32 m_unLastInput; - Uint32 m_unLastIMUReset; - Uint32 m_unIMUSampleTimestamp; + Uint64 m_ulLastInput; + Uint64 m_ulLastIMUReset; + Uint64 m_ulIMUSampleTimestampNS; Uint32 m_unIMUSamples; - Uint32 m_unIMUUpdateIntervalUS; - Uint64 m_ulTimestampUS; + Uint64 m_ulIMUUpdateIntervalNS; + Uint64 m_ulTimestampNS; SDL_bool m_bVerticalMode; 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) { /* Average response time for messages is ~30ms */ - Uint32 TimeoutMs = 100; - Uint32 startTicks = SDL_GetTicks(); + Uint64 endTicks = SDL_GetTicks() + 100; int nRead = 0; while ((nRead = ReadInput(ctx)) != -1) { @@ -345,7 +344,7 @@ static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Conte SDL_Delay(1); } - if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) { + if (SDL_GetTicks() >= endTicks) { break; } } @@ -355,8 +354,7 @@ static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Conte static SDL_bool ReadProprietaryReply(SDL_DriverSwitch_Context *ctx, ESwitchProprietaryCommandIDs expectedID) { /* Average response time for messages is ~30ms */ - Uint32 TimeoutMs = 100; - Uint32 startTicks = SDL_GetTicks(); + Uint64 endTicks = SDL_GetTicks() + 100; int nRead = 0; while ((nRead = ReadInput(ctx)) != -1) { @@ -368,7 +366,7 @@ static SDL_bool ReadProprietaryReply(SDL_DriverSwitch_Context *ctx, ESwitchPropr SDL_Delay(1); } - if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) { + if (SDL_GetTicks() >= endTicks) { break; } } @@ -536,7 +534,7 @@ static SDL_bool WriteRumble(SDL_DriverSwitch_Context *ctx) ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF; /* 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)); } @@ -1370,8 +1368,8 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ /* Set up for input */ ctx->m_bSyncWrite = SDL_FALSE; - ctx->m_unLastIMUReset = ctx->m_unLastInput = SDL_GetTicks(); - ctx->m_unIMUUpdateIntervalUS = 5 * 1000; /* Start off at 5 ms update rate */ + ctx->m_ulLastIMUReset = ctx->m_ulLastInput = SDL_GetTicks(); + ctx->m_ulIMUUpdateIntervalNS = SDL_MS_TO_NS(5); /* Start off at 5 ms update rate */ /* Set up for vertical mode */ 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) { - 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; } @@ -1419,7 +1417,7 @@ static int HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx) Uint16 high_frequency_rumble = (Uint16)ctx->m_unRumblePending; #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 ctx->m_bRumblePending = SDL_FALSE; ctx->m_unRumblePending = 0; @@ -1431,7 +1429,7 @@ static int HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx) ctx->m_bRumbleZeroPending = SDL_FALSE; #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 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) { 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); ctx->m_bReportSensors = enabled; ctx->m_unIMUSamples = 0; - ctx->m_unIMUSampleTimestamp = SDL_GetTicks(); + ctx->m_ulIMUSampleTimestampNS = SDL_GetTicksNS(); 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 */ ctx->m_unIMUSamples += 3; if (ctx->m_unIMUSamples >= IMU_UPDATE_RATE_SAMPLE_FREQUENCY) { - Uint32 now = SDL_GetTicks(); - Uint32 elapsed = (now - ctx->m_unIMUSampleTimestamp); + Uint64 now = SDL_GetTicksNS(); + Uint64 elapsed = (now - ctx->m_ulIMUSampleTimestampNS); if (elapsed > 0) { - ctx->m_unIMUUpdateIntervalUS = (elapsed * 1000) / ctx->m_unIMUSamples; + ctx->m_ulIMUUpdateIntervalNS = elapsed / ctx->m_unIMUSamples; } ctx->m_unIMUSamples = 0; - ctx->m_unIMUSampleTimestamp = now; + ctx->m_ulIMUSampleTimestampNS = now; } - ctx->m_ulTimestampUS += ctx->m_unIMUUpdateIntervalUS; - timestamp[0] = ctx->m_ulTimestampUS; - ctx->m_ulTimestampUS += ctx->m_unIMUUpdateIntervalUS; - timestamp[1] = ctx->m_ulTimestampUS; - ctx->m_ulTimestampUS += ctx->m_unIMUUpdateIntervalUS; - timestamp[2] = ctx->m_ulTimestampUS; + ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS; + timestamp[0] = SDL_NS_TO_US(ctx->m_ulTimestampNS); + ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS; + timestamp[1] = SDL_NS_TO_US(ctx->m_ulTimestampNS); + ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS; + timestamp[2] = SDL_NS_TO_US(ctx->m_ulTimestampNS); if (!ctx->device->parent || ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) { @@ -2042,10 +2040,10 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C } else if (ctx->m_bHasSensorData) { /* Uh oh, someone turned off the IMU? */ - const Uint32 IMU_RESET_DELAY_MS = 3000; - Uint32 now = SDL_GetTicks(); + const int IMU_RESET_DELAY_MS = 3000; + 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; if (device->updating) { @@ -2057,7 +2055,7 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C if (device->updating) { SDL_LockMutex(device->dev_lock); } - ctx->m_unLastIMUReset = now; + ctx->m_ulLastIMUReset = now; } } else { @@ -2074,7 +2072,7 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) SDL_Joystick *joystick = NULL; int size; int packet_count = 0; - Uint32 now = SDL_GetTicks(); + Uint64 now = SDL_GetTicks(); if (device->num_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); #endif ++packet_count; - ctx->m_unLastInput = now; + ctx->m_ulLastInput = now; if (joystick == NULL) { continue; @@ -2111,14 +2109,14 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) if (packet_count == 0) { if (!ctx->m_bInputOnly && !device->is_bluetooth && ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { - const Uint32 INPUT_WAIT_TIMEOUT_MS = 100; - if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { + const int INPUT_WAIT_TIMEOUT_MS = 100; + if (now >= (ctx->m_ulLastInput + INPUT_WAIT_TIMEOUT_MS)) { /* Steam may have put the controller back into non-reporting mode */ WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE); } } else if (device->is_bluetooth) { - const Uint32 INPUT_WAIT_TIMEOUT_MS = 3000; - if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { + const int INPUT_WAIT_TIMEOUT_MS = 3000; + if (now >= (ctx->m_ulLastInput + INPUT_WAIT_TIMEOUT_MS)) { /* Bluetooth may have disconnected, try reopening the controller */ size = -1; } @@ -2128,9 +2126,9 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) if (ctx->m_bRumblePending || ctx->m_bRumbleZeroPending) { HIDAPI_DriverSwitch_SendPendingRumble(ctx); } 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 - 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 WriteRumble(ctx); } diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index be6994bf3..2a5521712 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -142,9 +142,9 @@ typedef struct Uint8 m_ucMotionPlusMode; SDL_bool m_bReportSensors; Uint8 m_rgucReadBuffer[k_unWiiPacketDataLength]; - Uint32 m_unLastInput; - Uint32 m_unLastStatus; - Uint32 m_unNextMotionPlusCheck; + Uint64 m_ulLastInput; + Uint64 m_ulLastStatus; + Uint64 m_ulNextMotionPlusCheck; SDL_bool m_bDisconnected; 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 *)) { - Uint32 TimeoutMs = 250; /* Seeing successful reads after about 200 ms */ - Uint32 startTicks = SDL_GetTicks(); + Uint64 endTicks = SDL_GetTicks() + 250; /* Seeing successful reads after about 200 ms */ int nRead = 0; while ((nRead = ReadInput(ctx)) != -1) { @@ -235,7 +234,7 @@ static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs exp return SDL_TRUE; } } else { - if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) { + if (SDL_GetTicks() >= endTicks) { break; } SDL_Delay(1); @@ -443,10 +442,7 @@ static SDL_bool NeedsPeriodicMotionPlusCheck(SDL_DriverWii_Context *ctx, SDL_boo static void SchedulePeriodicMotionPlusCheck(SDL_DriverWii_Context *ctx) { - ctx->m_unNextMotionPlusCheck = SDL_GetTicks() + MOTION_PLUS_UPDATE_TIME_MS; - if (!ctx->m_unNextMotionPlusCheck) { - ctx->m_unNextMotionPlusCheck = 1; - } + ctx->m_ulNextMotionPlusCheck = SDL_GetTicks() + MOTION_PLUS_UPDATE_TIME_MS; } 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; - ctx->m_unLastInput = SDL_GetTicks(); + ctx->m_ulLastInput = SDL_GetTicks(); return SDL_TRUE; } @@ -1433,7 +1429,7 @@ static void HandleStatus(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick) * Motion Plus packets. */ if (NeedsPeriodicMotionPlusCheck(ctx, SDL_TRUE)) { - ctx->m_unNextMotionPlusCheck = SDL_GetTicks(); + ctx->m_ulNextMotionPlusCheck = SDL_GetTicks(); } } 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_Joystick *joystick = NULL; int size; - Uint32 now; + Uint64 now; if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); @@ -1582,7 +1578,7 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device) if (joystick) { HandleInput(ctx, joystick); } - ctx->m_unLastInput = now; + ctx->m_ulLastInput = now; } /* 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); } - 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 */ size = -1; } @@ -1601,26 +1597,24 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device) if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_WiiUPro) { /* Check to see if the Motion Plus extension status has changed */ - if (ctx->m_unNextMotionPlusCheck && - SDL_TICKS_PASSED(now, ctx->m_unNextMotionPlusCheck)) { + if (ctx->m_ulNextMotionPlusCheck && now >= ctx->m_ulNextMotionPlusCheck) { CheckMotionPlusConnection(ctx); if (NeedsPeriodicMotionPlusCheck(ctx, SDL_FALSE)) { SchedulePeriodicMotionPlusCheck(ctx); } else { - ctx->m_unNextMotionPlusCheck = 0; + ctx->m_ulNextMotionPlusCheck = 0; } } /* Request a status update periodically to make sure our battery value is up to date */ - if (!ctx->m_unLastStatus || - SDL_TICKS_PASSED(now, ctx->m_unLastStatus + STATUS_UPDATE_TIME_MS)) { + if (!ctx->m_ulLastStatus || now >= (ctx->m_ulLastStatus + STATUS_UPDATE_TIME_MS)) { Uint8 data[2]; data[0] = k_eWiiOutputReportIDs_StatusRequest; data[1] = ctx->m_bRumbleActive; WriteOutput(ctx, data, sizeof(data), SDL_FALSE); - ctx->m_unLastStatus = now; + ctx->m_ulLastStatus = now; } } } diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 05796d235..6d8ef1ca9 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -117,9 +117,9 @@ typedef struct SDL_bool bluetooth; SDL_XboxOneInitState init_state; int init_packet; - Uint32 start_time; + Uint64 start_time; Uint8 sequence; - Uint32 send_time; + Uint64 send_time; SDL_bool has_guide_packet; SDL_bool has_color_led; SDL_bool has_paddles; @@ -132,7 +132,7 @@ typedef struct Uint8 left_trigger_rumble; Uint8 right_trigger_rumble; SDL_XboxOneRumbleState rumble_state; - Uint32 rumble_time; + Uint64 rumble_time; SDL_bool rumble_pending; Uint8 last_state[USB_PACKET_LENGTH]; } 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) { - const Uint32 RUMBLE_BUSY_TIME_MS = ctx->bluetooth ? 50 : 10; - if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->rumble_time + RUMBLE_BUSY_TIME_MS)) { + const int RUMBLE_BUSY_TIME_MS = ctx->bluetooth ? 50 : 10; + if (SDL_GetTicks() >= (ctx->rumble_time + RUMBLE_BUSY_TIME_MS)) { ctx->rumble_time = 0; ctx->rumble_state = XBOX_ONE_RUMBLE_STATE_IDLE; } @@ -1087,7 +1087,7 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateInitState(SDL_HIDAPI_Device *device, #endif break; 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 */ #ifdef DEBUG_JOYSTICK 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; 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 SDL_Log("Prepare input complete after %u ms\n", (SDL_GetTicks() - ctx->send_time)); #endif diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index fc3a66222..6cd4e206c 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -119,7 +119,7 @@ static SDL_joylist_item *SDL_joylist_tail = NULL; static int numjoysticks = 0; 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 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) { 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; /* Opening input devices can generate synchronous device I/O, so avoid it if we can */ diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 04deee872..9c963247b 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -129,7 +129,7 @@ struct joystick_hwdata #ifdef SDL_JOYSTICK_RAWINPUT_MATCHING Uint64 match_state; /* Lowest 16 bits for button states, higher 24 for 6 4bit axes */ - Uint32 last_state_packet; + Uint64 last_state_packet; #endif #ifdef SDL_JOYSTICK_RAWINPUT_XINPUT @@ -167,7 +167,7 @@ static const Uint16 subscribed_devices[] = { static struct { - Uint32 last_state_packet; + Uint64 last_state_packet; SDL_Joystick *joystick; SDL_Joystick *last_joystick; } guide_button_candidate; @@ -1808,7 +1808,7 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick) if (!correlated) { if (!guide_button_candidate.joystick || (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.last_state_packet = ctx->last_state_packet; } diff --git a/src/power/uikit/SDL_syspower.m b/src/power/uikit/SDL_syspower.m index 4851cef2f..30026c8c2 100644 --- a/src/power/uikit/SDL_syspower.m +++ b/src/power/uikit/SDL_syspower.m @@ -30,12 +30,12 @@ #if !TARGET_OS_TV /* turn off the battery monitor if it's been more than X ms since last check. */ static const int BATTERY_MONITORING_TIMEOUT = 3000; -static Uint32 SDL_UIKitLastPowerInfoQuery = 0; +static Uint64 SDL_UIKitLastPowerInfoQuery = 0; void SDL_UIKit_UpdateBatteryMonitoring(void) { 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]; SDL_assert([uidev isBatteryMonitoringEnabled] == YES); [uidev setBatteryMonitoringEnabled:NO]; diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index fb99d78ac..f4ac775e5 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -921,7 +921,7 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind /* Pick a good default refresh rate */ 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 */ @@ -4188,24 +4188,24 @@ int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, static void SDL_RenderSimulateVSync(SDL_Renderer *renderer) { - Uint32 now, elapsed; - const Uint32 interval = renderer->simulate_vsync_interval; + Uint64 now, elapsed; + const Uint64 interval = renderer->simulate_vsync_interval_ns; 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; } - now = SDL_GetTicks(); + now = SDL_GetTicksNS(); elapsed = (now - renderer->last_present); if (elapsed < interval) { - Uint32 duration = (interval - elapsed); - SDL_Delay(duration); - now = SDL_GetTicks(); + Uint64 duration = (interval - elapsed); + SDL_DelayNS(duration); + now = SDL_GetTicksNS(); } 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 */ renderer->last_present = now; } else { diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 1fccc76da..78cc009e6 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -209,8 +209,8 @@ struct SDL_Renderer /* Whether we should simulate vsync */ SDL_bool wanted_vsync; SDL_bool simulate_vsync; - Uint32 simulate_vsync_interval; - Uint32 last_present; + Uint64 simulate_vsync_interval_ns; + Uint64 last_present; /* The logical resolution for rendering */ int logical_w; diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index c815b2fc5..b6a73b956 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -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: */ diff --git a/src/thread/generic/SDL_syscond.c b/src/thread/generic/SDL_syscond.c index ff5ea9676..d9f0a0f83 100644 --- a/src/thread/generic/SDL_syscond.c +++ b/src/thread/generic/SDL_syscond.c @@ -37,8 +37,7 @@ #define SDL_DestroyCond_generic SDL_DestroyCond #define SDL_CondSignal_generic SDL_CondSignal #define SDL_CondBroadcast_generic SDL_CondBroadcast -#define SDL_CondWait_generic SDL_CondWait -#define SDL_CondWaitTimeout_generic SDL_CondWaitTimeout +#define SDL_CondWaitTimeoutNS_generic SDL_CondWaitTimeoutNS #endif typedef struct SDL_cond_generic @@ -148,7 +147,7 @@ int SDL_CondBroadcast_generic(SDL_cond *_cond) 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 is unlocked during the wait, and locked again after the wait. @@ -169,7 +168,7 @@ Thread B: SDL_CondSignal(cond); 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; int retval; @@ -190,11 +189,7 @@ int SDL_CondWaitTimeout_generic(SDL_cond *_cond, SDL_mutex *mutex, Uint32 ms) SDL_UnlockMutex(mutex); /* Wait for a signal */ - if (ms == SDL_MUTEX_MAXWAIT) { - retval = SDL_SemWait(cond->wait_sem); - } else { - retval = SDL_SemWaitTimeout(cond->wait_sem, ms); - } + retval = SDL_SemWaitTimeoutNS(cond->wait_sem, timeoutNS); /* Let the signaler know we have completed the wait, otherwise 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; } -/* 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: */ diff --git a/src/thread/generic/SDL_syscond_c.h b/src/thread/generic/SDL_syscond_c.h index a2d080245..8c4238239 100644 --- a/src/thread/generic/SDL_syscond_c.h +++ b/src/thread/generic/SDL_syscond_c.h @@ -29,9 +29,7 @@ SDL_cond *SDL_CreateCond_generic(void); void SDL_DestroyCond_generic(SDL_cond *cond); int SDL_CondSignal_generic(SDL_cond *cond); int SDL_CondBroadcast_generic(SDL_cond *cond); -int SDL_CondWait_generic(SDL_cond *cond, SDL_mutex *mutex); -int SDL_CondWaitTimeout_generic(SDL_cond *cond, - SDL_mutex *mutex, Uint32 ms); +int SDL_CondWaitTimeoutNS_generic(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS); #endif /* SDL_THREAD_GENERIC_COND_SUFFIX */ diff --git a/src/thread/generic/SDL_syssem.c b/src/thread/generic/SDL_syssem.c index 20332be71..05d4641f3 100644 --- a/src/thread/generic/SDL_syssem.c +++ b/src/thread/generic/SDL_syssem.c @@ -37,17 +37,7 @@ void SDL_DestroySemaphore(SDL_sem *sem) { } -int SDL_SemTryWait(SDL_sem *sem) -{ - 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) +int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS) { return SDL_SetError("SDL not built with thread support"); } @@ -117,26 +107,7 @@ void SDL_DestroySemaphore(SDL_sem *sem) } } -int SDL_SemTryWait(SDL_sem *sem) -{ - int retval; - - if (sem == NULL) { - return SDL_InvalidParamError("sem"); - } - - retval = SDL_MUTEX_TIMEDOUT; - SDL_LockMutex(sem->count_lock); - if (sem->count > 0) { - --sem->count; - retval = 0; - } - SDL_UnlockMutex(sem->count_lock); - - return retval; -} - -int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS) { int retval; @@ -145,16 +116,24 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) } /* A timeout of 0 is an easy case */ - if (timeout == 0) { - return SDL_SemTryWait(sem); + if (timeoutNS == 0) { + retval = SDL_MUTEX_TIMEDOUT; + SDL_LockMutex(sem->count_lock); + if (sem->count > 0) { + --sem->count; + retval = 0; + } + SDL_UnlockMutex(sem->count_lock); + + return retval; } SDL_LockMutex(sem->count_lock); ++sem->waiters_count; retval = 0; while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) { - retval = SDL_CondWaitTimeout(sem->count_nonzero, - sem->count_lock, timeout); + retval = SDL_CondWaitTimeoutNS(sem->count_nonzero, + sem->count_lock, timeoutNS); } --sem->waiters_count; if (retval == 0) { @@ -165,11 +144,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) return retval; } -int SDL_SemWait(SDL_sem *sem) -{ - return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); -} - Uint32 SDL_SemValue(SDL_sem *sem) { @@ -201,4 +175,5 @@ int SDL_SemPost(SDL_sem *sem) } #endif /* SDL_THREADS_DISABLED */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/n3ds/SDL_syscond.c b/src/thread/n3ds/SDL_syscond.c index 237cf48f9..d33997276 100644 --- a/src/thread/n3ds/SDL_syscond.c +++ b/src/thread/n3ds/SDL_syscond.c @@ -74,7 +74,7 @@ int SDL_CondBroadcast(SDL_cond *cond) 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 is unlocked during the wait, and locked again after the wait. @@ -95,7 +95,7 @@ Thread B: SDL_CondSignal(cond); 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; @@ -107,22 +107,15 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) } res = 0; - if (ms == SDL_MUTEX_MAXWAIT) { + if (timeoutNS < 0) { CondVar_Wait(&cond->cond_variable, &mutex->lock.lock); } else { - res = CondVar_WaitTimeout(&cond->cond_variable, &mutex->lock.lock, - (s64)ms * 1000000LL); + res = CondVar_WaitTimeout(&cond->cond_variable, &mutex->lock.lock, timeoutNS); } 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 */ /* vi: set sts=4 ts=4 sw=4 expandtab: */ diff --git a/src/thread/n3ds/SDL_syssem.c b/src/thread/n3ds/SDL_syssem.c index a89b57d64..8cd381f5c 100644 --- a/src/thread/n3ds/SDL_syssem.c +++ b/src/thread/n3ds/SDL_syssem.c @@ -62,16 +62,7 @@ void SDL_DestroySemaphore(SDL_sem *sem) } } -int SDL_SemTryWait(SDL_sem *sem) -{ - if (sem == NULL) { - return SDL_InvalidParamError("sem"); - } - - return SDL_SemWaitTimeout(sem, 0); -} - -int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS) { int retval; @@ -79,12 +70,15 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) return SDL_InvalidParamError("sem"); } - if (timeout == SDL_MUTEX_MAXWAIT) { + if (timeoutNS == SDL_MUTEX_MAXWAIT) { LightSemaphore_Acquire(&sem->semaphore, 1); retval = 0; } else { int return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1); 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++) { svcSleepThread(1000000LL); return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1); @@ -99,11 +93,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) return retval; } -int SDL_SemWait(SDL_sem *sem) -{ - return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); -} - Uint32 SDL_SemValue(SDL_sem *sem) { diff --git a/src/thread/ngage/SDL_syssem.cpp b/src/thread/ngage/SDL_syssem.cpp index 6bdc93286..6e3737227 100644 --- a/src/thread/ngage/SDL_syssem.cpp +++ b/src/thread/ngage/SDL_syssem.cpp @@ -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) { 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); - return SDL_MUTEX_MAXWAIT; + return 0; } 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); if (status != KErrNone) { @@ -130,23 +138,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 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 SDL_SemValue(SDL_sem *sem) { diff --git a/src/thread/ps2/SDL_syssem.c b/src/thread/ps2/SDL_syssem.c index 23141517b..585178fe3 100644 --- a/src/thread/ps2/SDL_syssem.c +++ b/src/thread/ps2/SDL_syssem.c @@ -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; struct timer_alarm_t alarm; @@ -89,15 +89,15 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) return SDL_InvalidParamError("sem"); } - if (timeout == 0) { + if (timeoutNS == 0) { if (PollSema(sem->semid) < 0) { return SDL_MUTEX_TIMEDOUT; } return 0; } - if (timeout != SDL_MUTEX_MAXWAIT) { - SetTimerAlarm(&alarm, MSec2TimerBusClock(timeout), &usercb, (void *)GetThreadId()); + if (timeoutNS != SDL_MUTEX_MAXWAIT) { + SetTimerAlarm(&alarm, MSec2TimerBusClock(SDL_NS_TO_MS(timeoutNS)), &usercb, (void *)GetThreadId()); } ret = WaitSema(sem->semid); @@ -109,16 +109,6 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 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 */ Uint32 SDL_SemValue(SDL_sem *sem) { diff --git a/src/thread/psp/SDL_syscond.c b/src/thread/psp/SDL_syscond.c index 44eae6527..89933bc8b 100644 --- a/src/thread/psp/SDL_syscond.c +++ b/src/thread/psp/SDL_syscond.c @@ -132,7 +132,7 @@ int SDL_CondBroadcast(SDL_cond *cond) 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 is unlocked during the wait, and locked again after the wait. @@ -153,7 +153,7 @@ Thread B: SDL_CondSignal(cond); 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; @@ -173,11 +173,7 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) SDL_UnlockMutex(mutex); /* Wait for a signal */ - if (ms == SDL_MUTEX_MAXWAIT) { - retval = SDL_SemWait(cond->wait_sem); - } else { - retval = SDL_SemWaitTimeout(cond->wait_sem, ms); - } + retval = SDL_SemWaitTimeout(cond->wait_sem, timeoutNS); /* Let the signaler know we have completed the wait, otherwise 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; } -/* 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 */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/psp/SDL_syssem.c b/src/thread/psp/SDL_syssem.c index fe55cadda..fe904b6dd 100644 --- a/src/thread/psp/SDL_syssem.c +++ b/src/thread/psp/SDL_syssem.c @@ -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 * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout * 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; if (sem == NULL) { return SDL_InvalidParamError("sem"); } - if (timeout == 0) { + if (timeoutNS == 0) { res = sceKernelPollSema(sem->semid, 1); if (res < 0) { return SDL_MUTEX_TIMEDOUT; @@ -90,14 +91,14 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) return 0; } - if (timeout == SDL_MUTEX_MAXWAIT) { + if (timeoutNS < 0) { pTimeout = NULL; } else { - timeout *= 1000; /* Convert to microseconds. */ - pTimeout = &timeout; + timeoutUS = (SceUInt)SDL_NS_TO_US(timeoutNS); /* Convert to microseconds. */ + pTimeout = &timeoutUS; } - res = sceKernelWaitSema(sem->semid, 1, (SceUInt *)pTimeout); + res = sceKernelWaitSema(sem->semid, 1, pTimeout); switch (res) { case SCE_KERNEL_ERROR_OK: 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 */ Uint32 SDL_SemValue(SDL_sem *sem) { diff --git a/src/thread/pthread/SDL_syscond.c b/src/thread/pthread/SDL_syscond.c index 9c44bbe89..9b0534caf 100644 --- a/src/thread/pthread/SDL_syscond.c +++ b/src/thread/pthread/SDL_syscond.c @@ -91,7 +91,7 @@ int SDL_CondBroadcast(SDL_cond *cond) 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; #ifndef HAVE_CLOCK_GETTIME @@ -103,18 +103,25 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) 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 clock_gettime(CLOCK_REALTIME, &abstime); - abstime.tv_nsec += (ms % 1000) * 1000000; - abstime.tv_sec += ms / 1000; + abstime.tv_sec += (timeoutNS / SDL_NS_PER_SECOND); + abstime.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND); #else gettimeofday(&delta, NULL); - abstime.tv_sec = delta.tv_sec + (ms / 1000); - abstime.tv_nsec = (long)(delta.tv_usec + (ms % 1000) * 1000) * 1000; + abstime.tv_sec = delta.tv_sec + (timeoutNS / SDL_NS_PER_SECOND); + abstime.tv_nsec = SDL_US_TO_NS(delta.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND); #endif - if (abstime.tv_nsec > 1000000000) { + while (abstime.tv_nsec > 1000000000) { abstime.tv_sec += 1; abstime.tv_nsec -= 1000000000; } @@ -136,17 +143,4 @@ tryagain: 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: */ diff --git a/src/thread/pthread/SDL_syssem.c b/src/thread/pthread/SDL_syssem.c index d68f2e029..65179461a 100644 --- a/src/thread/pthread/SDL_syssem.c +++ b/src/thread/pthread/SDL_syssem.c @@ -63,39 +63,7 @@ void SDL_DestroySemaphore(SDL_sem *sem) } } -int SDL_SemTryWait(SDL_sem *sem) -{ - 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 SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS) { int retval; #ifdef HAVE_SEM_TIMEDWAIT @@ -104,7 +72,7 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) #endif struct timespec ts_timeout; #else - Uint32 end; + Uint64 end; #endif if (sem == NULL) { @@ -112,11 +80,22 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) } /* Try the easy cases first */ - if (timeout == 0) { - return SDL_SemTryWait(sem); + if (timeoutNS == 0) { + retval = SDL_MUTEX_TIMEDOUT; + if (sem_trywait(&sem->sem) == 0) { + retval = 0; + } + return retval; } - if (timeout == SDL_MUTEX_MAXWAIT) { - 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 @@ -128,18 +107,18 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) clock_gettime(CLOCK_REALTIME, &ts_timeout); /* Add our timeout to current time */ - ts_timeout.tv_nsec += (timeout % 1000) * 1000000; - ts_timeout.tv_sec += timeout / 1000; + ts_timeout.tv_sec += (timeoutNS / SDL_NS_PER_SECOND); + ts_timeout.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND); #else gettimeofday(&now, NULL); /* Add our timeout to current time */ - ts_timeout.tv_sec = now.tv_sec + (timeout / 1000); - ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000; + ts_timeout.tv_sec = now.tv_sec + (timeoutNS / SDL_NS_PER_SECOND); + ts_timeout.tv_nsec = SDL_US_TO_NS(now.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND); #endif /* 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_nsec -= 1000000000; } @@ -157,12 +136,13 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) } } #else - end = SDL_GetTicks() + timeout; - while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) { - if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) { + end = SDL_GetTicksNS() + timeoutNS; + while (sem_trywait(&sem->sem) != 0) { + if (SDL_GetTicksNS() >= end) { + retval = SDL_MUTEX_TIMEDOUT; break; } - SDL_Delay(1); + SDL_DelayNS(100); } #endif /* HAVE_SEM_TIMEDWAIT */ diff --git a/src/thread/stdcpp/SDL_syscond.cpp b/src/thread/stdcpp/SDL_syscond.cpp index 4cc20c731..0239edacf 100644 --- a/src/thread/stdcpp/SDL_syscond.cpp +++ b/src/thread/stdcpp/SDL_syscond.cpp @@ -85,7 +85,7 @@ SDL_CondBroadcast(SDL_cond *cond) 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 is unlocked during the wait, and locked again after the wait. @@ -107,7 +107,7 @@ Thread B: SDL_UnlockMutex(lock); */ 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) { return SDL_InvalidParamError("cond"); @@ -119,7 +119,7 @@ SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) try { std::unique_lock cpp_lock(mutex->cpp_mutex, std::adopt_lock_t()); - if (ms == SDL_MUTEX_MAXWAIT) { + if (timeoutNS < 0) { cond->cpp_cond.wait( cpp_lock); cpp_lock.release(); @@ -127,7 +127,7 @@ SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) } else { auto wait_result = cond->cpp_cond.wait_for( cpp_lock, - std::chrono::duration(ms)); + std::chrono::duration(timeoutNS)); cpp_lock.release(); if (wait_result == std::cv_status::timeout) { return SDL_MUTEX_TIMEDOUT; @@ -136,15 +136,8 @@ SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) } } } 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: */ diff --git a/src/thread/vita/SDL_syscond.c b/src/thread/vita/SDL_syscond.c index bc47f112e..ca5153cb8 100644 --- a/src/thread/vita/SDL_syscond.c +++ b/src/thread/vita/SDL_syscond.c @@ -132,7 +132,7 @@ int SDL_CondBroadcast(SDL_cond *cond) 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 is unlocked during the wait, and locked again after the wait. @@ -153,7 +153,7 @@ Thread B: SDL_CondSignal(cond); 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; @@ -173,11 +173,7 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) SDL_UnlockMutex(mutex); /* Wait for a signal */ - if (ms == SDL_MUTEX_MAXWAIT) { - retval = SDL_SemWait(cond->wait_sem); - } else { - retval = SDL_SemWaitTimeout(cond->wait_sem, ms); - } + retval = SDL_SemWaitTimeoutNS(cond->wait_sem, timeoutNS); /* Let the signaler know we have completed the wait, otherwise 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; } -/* 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 */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/vita/SDL_syssem.c b/src/thread/vita/SDL_syssem.c index ccc24d20f..b5f856bd3 100644 --- a/src/thread/vita/SDL_syssem.c +++ b/src/thread/vita/SDL_syssem.c @@ -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 * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout * 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; if (sem == NULL) { return SDL_InvalidParamError("sem"); } - if (timeout == 0) { + if (timeoutNS == 0) { res = sceKernelPollSema(sem->semid, 1); if (res < 0) { return SDL_MUTEX_TIMEDOUT; @@ -91,11 +92,11 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) return 0; } - if (timeout == SDL_MUTEX_MAXWAIT) { + if (timeoutNS < 0) { pTimeout = NULL; } else { - timeout *= 1000; /* Convert to microseconds. */ - pTimeout = &timeout; + timeoutUS = (SceUInt)SDL_NS_TO_US(timeoutNS); /* Convert to microseconds. */ + pTimeout = &timeoutUS; } res = sceKernelWaitSema(sem->semid, 1, pTimeout); @@ -105,20 +106,10 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) case SCE_KERNEL_ERROR_WAIT_TIMEOUT: return SDL_MUTEX_TIMEDOUT; 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 */ Uint32 SDL_SemValue(SDL_sem *sem) { diff --git a/src/thread/windows/SDL_syscond_cv.c b/src/thread/windows/SDL_syscond_cv.c index 441c7ff73..c2c8a750b 100644 --- a/src/thread/windows/SDL_syscond_cv.c +++ b/src/thread/windows/SDL_syscond_cv.c @@ -27,8 +27,7 @@ typedef SDL_cond *(*pfnSDL_CreateCond)(void); typedef void (*pfnSDL_DestroyCond)(SDL_cond *); typedef int (*pfnSDL_CondSignal)(SDL_cond *); typedef int (*pfnSDL_CondBroadcast)(SDL_cond *); -typedef int (*pfnSDL_CondWait)(SDL_cond *, SDL_mutex *); -typedef int (*pfnSDL_CondWaitTimeout)(SDL_cond *, SDL_mutex *, Uint32); +typedef int (*pfnSDL_CondWaitTimeoutNS)(SDL_cond *, SDL_mutex *, Sint64); typedef struct SDL_cond_impl_t { @@ -36,8 +35,7 @@ typedef struct SDL_cond_impl_t pfnSDL_DestroyCond Destroy; pfnSDL_CondSignal Signal; pfnSDL_CondBroadcast Broadcast; - pfnSDL_CondWait Wait; - pfnSDL_CondWaitTimeout WaitTimeout; + pfnSDL_CondWaitTimeoutNS WaitTimeoutNS; } SDL_cond_impl_t; /* 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; } -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; DWORD timeout; @@ -138,10 +136,10 @@ static int SDL_CondWaitTimeout_cv(SDL_cond *_cond, SDL_mutex *_mutex, Uint32 ms) return SDL_InvalidParamError("mutex"); } - if (ms == SDL_MUTEX_MAXWAIT) { + if (timeoutNS < 0) { timeout = INFINITE; } else { - timeout = (DWORD)ms; + timeout = (DWORD)SDL_NS_TO_MS(timeoutNS); } 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; } -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 = { &SDL_CreateCond_cv, &SDL_DestroyCond_cv, &SDL_CondSignal_cv, &SDL_CondBroadcast_cv, - &SDL_CondWait_cv, - &SDL_CondWaitTimeout_cv, + &SDL_CondWaitTimeoutNS_cv, }; /** @@ -211,8 +203,7 @@ static const SDL_cond_impl_t SDL_cond_impl_generic = { &SDL_DestroyCond_generic, &SDL_CondSignal_generic, &SDL_CondBroadcast_generic, - &SDL_CondWait_generic, - &SDL_CondWaitTimeout_generic, + &SDL_CondWaitTimeoutNS_generic, }; SDL_cond * @@ -272,14 +263,9 @@ int SDL_CondBroadcast(SDL_cond *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); -} - -int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) -{ - return SDL_cond_impl_active.Wait(cond, mutex); + return SDL_cond_impl_active.WaitTimeoutNS(cond, mutex, timeoutNS); } /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/windows/SDL_syssem.c b/src/thread/windows/SDL_syssem.c index 000b856f2..9961f937e 100644 --- a/src/thread/windows/SDL_syssem.c +++ b/src/thread/windows/SDL_syssem.c @@ -37,9 +37,7 @@ typedef SDL_sem *(*pfnSDL_CreateSemaphore)(Uint32); typedef void (*pfnSDL_DestroySemaphore)(SDL_sem *); -typedef int (*pfnSDL_SemWaitTimeout)(SDL_sem *, Uint32); -typedef int (*pfnSDL_SemTryWait)(SDL_sem *); -typedef int (*pfnSDL_SemWait)(SDL_sem *); +typedef int (*pfnSDL_SemWaitTimeoutNS)(SDL_sem *, Sint64); typedef Uint32 (*pfnSDL_SemValue)(SDL_sem *); typedef int (*pfnSDL_SemPost)(SDL_sem *); @@ -47,9 +45,7 @@ typedef struct SDL_semaphore_impl_t { pfnSDL_CreateSemaphore Create; pfnSDL_DestroySemaphore Destroy; - pfnSDL_SemWaitTimeout WaitTimeout; - pfnSDL_SemTryWait TryWait; - pfnSDL_SemWait Wait; + pfnSDL_SemWaitTimeoutNS WaitTimeoutNS; pfnSDL_SemValue Value; pfnSDL_SemPost Post; } SDL_sem_impl_t; @@ -108,81 +104,60 @@ 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; LONG count; + Uint64 now; + Uint64 deadline; + DWORD timeout_eff; if (sem == NULL) { return SDL_InvalidParamError("sem"); } - count = sem->count; - if (count == 0) { - return SDL_MUTEX_TIMEDOUT; - } - - if (InterlockedCompareExchange(&sem->count, count - 1, count) == count) { - return 0; - } - - 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"); - } - - for (;;) { + if (timeoutNS == 0) { count = sem->count; - while (count == 0) { - if (pWaitOnAddress(&sem->count, &count, sizeof(sem->count), INFINITE) == FALSE) { - return SDL_SetError("WaitOnAddress() failed"); - } - count = sem->count; + if (count == 0) { + return SDL_MUTEX_TIMEDOUT; } if (InterlockedCompareExchange(&sem->count, count - 1, count) == count) { return 0; } + + return SDL_MUTEX_TIMEDOUT; } -} + if (timeoutNS < 0) { + for (;;) { + count = sem->count; + while (count == 0) { + if (pWaitOnAddress(&sem->count, &count, sizeof(sem->count), INFINITE) == FALSE) { + return SDL_SetError("WaitOnAddress() failed"); + } + count = sem->count; + } -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"); + if (InterlockedCompareExchange(&sem->count, count - 1, count) == count) { + return 0; + } + } } /** * WaitOnAddress is subject to spurious and stolen wakeups so we * need to recalculate the effective timeout before every wait */ - now = SDL_GetTicks(); - deadline = now + (DWORD)timeout; + now = SDL_GetTicksNS(); + deadline = now + timeoutNS; for (;;) { count = sem->count; /* If no semaphore is available we need to wait */ while (count == 0) { - now = SDL_GetTicks(); + now = SDL_GetTicksNS(); if (deadline > now) { - timeout_eff = deadline - now; + timeout_eff = (DWORD)SDL_NS_TO_MS(deadline - now); } else { 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 = { &SDL_CreateSemaphore_atom, &SDL_DestroySemaphore_atom, - &SDL_SemWaitTimeout_atom, - &SDL_SemTryWait_atom, - &SDL_SemWait_atom, + &SDL_SemWaitTimeoutNS_atom, &SDL_SemValue_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; int retval; @@ -299,10 +272,10 @@ static int SDL_SemWaitTimeout_kern(SDL_sem *_sem, Uint32 timeout) return SDL_InvalidParamError("sem"); } - if (timeout == SDL_MUTEX_MAXWAIT) { + if (timeoutNS < 0) { dwMilliseconds = INFINITE; } else { - dwMilliseconds = (DWORD)timeout; + dwMilliseconds = (DWORD)SDL_NS_TO_MS(timeoutNS); } switch (WaitForSingleObjectEx(sem->id, dwMilliseconds, FALSE)) { case WAIT_OBJECT_0: @@ -319,16 +292,6 @@ static int SDL_SemWaitTimeout_kern(SDL_sem *_sem, Uint32 timeout) 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 */ 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 = { &SDL_CreateSemaphore_kern, &SDL_DestroySemaphore_kern, - &SDL_SemWaitTimeout_kern, - &SDL_SemTryWait_kern, - &SDL_SemWait_kern, + &SDL_SemWaitTimeoutNS_kern, &SDL_SemValue_kern, &SDL_SemPost_kern, }; @@ -417,19 +378,9 @@ void SDL_DestroySemaphore(SDL_sem *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); -} - -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); + return SDL_sem_impl_active.WaitTimeoutNS(sem, timeoutNS); } Uint32 diff --git a/src/timer/SDL_timer.c b/src/timer/SDL_timer.c index a9fd5ab90..4601ecd86 100644 --- a/src/timer/SDL_timer.c +++ b/src/timer/SDL_timer.c @@ -32,8 +32,8 @@ typedef struct _SDL_Timer int timerID; SDL_TimerCallback callback; void *param; - Uint32 interval; - Uint32 scheduled; + Uint64 interval; + Uint64 scheduled; SDL_atomic_t canceled; struct _SDL_Timer *next; } SDL_Timer; @@ -82,7 +82,7 @@ static void SDL_AddTimerInternal(SDL_TimerData *data, SDL_Timer *timer) prev = NULL; for (curr = data->timers; curr; prev = curr, curr = curr->next) { - if ((Sint32)(timer->scheduled - curr->scheduled) < 0) { + if (curr->scheduled > timer->scheduled) { break; } } @@ -103,7 +103,7 @@ static int SDLCALL SDL_TimerThread(void *_data) SDL_Timer *current; SDL_Timer *freelist_head = NULL; SDL_Timer *freelist_tail = NULL; - Uint32 tick, now, interval, delay; + Uint64 tick, now, interval, delay; /* Threaded timer loop: * 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 */ delay = SDL_MUTEX_MAXWAIT; - tick = SDL_GetTicks(); + tick = SDL_GetTicksNS(); /* Process all the pending timers for this tick */ while (data->timers) { current = data->timers; - if ((Sint32)(tick - current->scheduled) < 0) { + if (tick < current->scheduled) { /* Scheduled for the future, wait a bit */ delay = (current->scheduled - tick); break; @@ -161,7 +161,8 @@ static int SDLCALL SDL_TimerThread(void *_data) if (SDL_AtomicGet(¤t->canceled)) { interval = 0; } 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) { @@ -183,7 +184,7 @@ static int SDLCALL SDL_TimerThread(void *_data) } /* Adjust the delay based on processing time */ - now = SDL_GetTicks(); + now = SDL_GetTicksNS(); interval = (now - tick); if (interval > delay) { 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 extra times. */ - SDL_SemWaitTimeout(data->sem, delay); + SDL_SemWaitTimeoutNS(data->sem, delay); } return 0; } @@ -271,8 +272,7 @@ void SDL_TimerQuit(void) } } -SDL_TimerID -SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) +SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) { SDL_TimerData *data = &SDL_timer_data; SDL_Timer *timer; @@ -304,8 +304,8 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) timer->timerID = SDL_AtomicIncRef(&data->nextID); timer->callback = callback; timer->param = param; - timer->interval = interval; - timer->scheduled = SDL_GetTicks() + interval; + timer->interval = SDL_MS_TO_NS(interval); + timer->scheduled = SDL_GetTicksNS() + timer->interval; SDL_AtomicSet(&timer->canceled, 0); entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); @@ -334,8 +334,7 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) return entry->timerID; } -SDL_bool -SDL_RemoveTimer(SDL_TimerID id) +SDL_bool SDL_RemoveTimer(SDL_TimerID id) { SDL_TimerData *data = &SDL_timer_data; SDL_TimerMap *prev, *entry; @@ -417,8 +416,7 @@ void SDL_TimerQuit(void) } } -SDL_TimerID -SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) +SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) { SDL_TimerData *data = &SDL_timer_data; SDL_TimerMap *entry; @@ -443,8 +441,7 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) return entry->timerID; } -SDL_bool -SDL_RemoveTimer(SDL_TimerID id) +SDL_bool SDL_RemoveTimer(SDL_TimerID id) { SDL_TimerData *data = &SDL_timer_data; SDL_TimerMap *prev, *entry; @@ -471,16 +468,94 @@ SDL_RemoveTimer(SDL_TimerID id) 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 +#define HAVE_TIME_BEGIN_PERIOD #endif -/* This is a legacy support function; SDL_GetTicks() returns a Uint32, - 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) +static void SDL_SetSystemTimerResolutionMS(int period) { - 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: */ diff --git a/src/timer/dummy/SDL_systimer.c b/src/timer/dummy/SDL_systimer.c index 0428b7d24..3dd417b0b 100644 --- a/src/timer/dummy/SDL_systimer.c +++ b/src/timer/dummy/SDL_systimer.c @@ -22,45 +22,20 @@ #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 -SDL_GetTicks64(void) +SDL_GetPerformanceCounter(void) { - if (!ticks_started) { - SDL_TicksInit(); - } - SDL_Unsupported(); return 0; } -Uint64 -SDL_GetPerformanceCounter(void) -{ - return SDL_GetTicks(); -} - Uint64 SDL_GetPerformanceFrequency(void) { - return 1000; + return 1; } -void SDL_Delay(Uint32 ms) +void SDL_DelayNS(Uint64 ns) { SDL_Unsupported(); } diff --git a/src/timer/haiku/SDL_systimer.c b/src/timer/haiku/SDL_systimer.c index 9424078b1..d832a632e 100644 --- a/src/timer/haiku/SDL_systimer.c +++ b/src/timer/haiku/SDL_systimer.c @@ -24,34 +24,6 @@ #include -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 SDL_GetPerformanceCounter(void) @@ -62,12 +34,12 @@ SDL_GetPerformanceCounter(void) Uint64 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 */ diff --git a/src/timer/n3ds/SDL_systimer.c b/src/timer/n3ds/SDL_systimer.c index ea2c28914..e109c4d5c 100644 --- a/src/timer/n3ds/SDL_systimer.c +++ b/src/timer/n3ds/SDL_systimer.c @@ -24,37 +24,6 @@ #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 SDL_GetPerformanceCounter(void) @@ -68,9 +37,9 @@ SDL_GetPerformanceFrequency(void) return SYSCLOCK_ARM11; } -void SDL_Delay(Uint32 ms) +void SDL_DelayNS(Uint64 ns) { - svcSleepThread(ms * NSEC_PER_MSEC); + svcSleepThread(ns); } #endif /* SDL_TIMER_N3DS */ diff --git a/src/timer/ngage/SDL_systimer.cpp b/src/timer/ngage/SDL_systimer.cpp index c72e61bb4..36b861487 100644 --- a/src/timer/ngage/SDL_systimer.cpp +++ b/src/timer/ngage/SDL_systimer.cpp @@ -25,63 +25,33 @@ #include #include -static SDL_bool ticks_started = SDL_FALSE; -static TUint start = 0; -static TInt tickPeriodMilliSeconds; +static TUint start_tick = 0; #ifdef __cplusplus extern "C" { #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 SDL_GetPerformanceCounter(void) { + /* FIXME: Need to account for 32-bit wrapping */ return (Uint64)User::TickCount(); } Uint64 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 diff --git a/src/timer/ps2/SDL_systimer.c b/src/timer/ps2/SDL_systimer.c index 5b228e320..0411efe6c 100644 --- a/src/timer/ps2/SDL_systimer.c +++ b/src/timer/ps2/SDL_systimer.c @@ -28,54 +28,24 @@ #include #include -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 SDL_GetPerformanceCounter(void) { - return SDL_GetTicks64(); + return GetTimerSystemTime(); } Uint64 SDL_GetPerformanceFrequency(void) { - return 1000; + return kBUSCLK; } -void SDL_Delay(Uint32 ms) +void SDL_DelayNS(Uint64 ns) { - struct timespec tv = { 0 }; - tv.tv_sec = ms / 1000; - tv.tv_nsec = (ms % 1000) * 1000000; + struct timespec tv; + tv.tv_sec = (ns / SDL_NS_PER_SECOND); + tv.tv_nsec = (ns % SDL_NS_PER_SECOND); nanosleep(&tv, NULL); } diff --git a/src/timer/psp/SDL_systimer.c b/src/timer/psp/SDL_systimer.c index 1fd8327e7..d1ddeac0e 100644 --- a/src/timer/psp/SDL_systimer.c +++ b/src/timer/psp/SDL_systimer.c @@ -28,56 +28,33 @@ #include #include -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 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 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; - if (ms > max_delay) { - ms = max_delay; + const Uint64 max_delay = 0xffffffff * SDL_NS_PER_US; + if (ns > max_delay) { + ns = max_delay; } - sceKernelDelayThreadCB(ms * 1000); + sceKernelDelayThreadCB((SceUInt)SDL_NS_TO_US(ns)); } #endif /* SDL_TIMER_PSP */ diff --git a/src/timer/unix/SDL_systimer.c b/src/timer/unix/SDL_systimer.c index ef068eb44..e5242b8fb 100644 --- a/src/timer/unix/SDL_systimer.c +++ b/src/timer/unix/SDL_systimer.c @@ -61,76 +61,34 @@ #endif /* The first ticks value of the application */ -#if HAVE_CLOCK_GETTIME -static struct timespec start_ts; -#elif defined(__APPLE__) -static uint64_t start_mach; +#if !defined(HAVE_CLOCK_GETTIME) && defined(__APPLE__) mach_timebase_info_data_t mach_base_info; #endif +static SDL_bool checked_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 (clock_gettime(SDL_MONOTONIC_CLOCK, &start_ts) == 0) { + struct timespec value; + if (clock_gettime(SDL_MONOTONIC_CLOCK, &value) == 0) { has_monotonic_time = SDL_TRUE; } else #elif defined(__APPLE__) if (mach_timebase_info(&mach_base_info) == 0) { has_monotonic_time = SDL_TRUE; - start_mach = mach_absolute_time(); - } else + } #endif - { - 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)); - } + checked_monotonic_time = SDL_TRUE; } Uint64 SDL_GetPerformanceCounter(void) { Uint64 ticks; - if (!ticks_started) { - SDL_TicksInit(); + + if (!checked_monotonic_time) { + CheckMonotonicTime(); } if (has_monotonic_time) { @@ -139,7 +97,7 @@ SDL_GetPerformanceCounter(void) clock_gettime(SDL_MONOTONIC_CLOCK, &now); ticks = now.tv_sec; - ticks *= 1000000000; + ticks *= SDL_NS_PER_SECOND; ticks += now.tv_nsec; #elif defined(__APPLE__) ticks = mach_absolute_time(); @@ -152,7 +110,7 @@ SDL_GetPerformanceCounter(void) gettimeofday(&now, NULL); ticks = now.tv_sec; - ticks *= 1000000; + ticks *= SDL_US_PER_SECOND; ticks += now.tv_usec; } return ticks; @@ -161,30 +119,30 @@ SDL_GetPerformanceCounter(void) Uint64 SDL_GetPerformanceFrequency(void) { - if (!ticks_started) { - SDL_TicksInit(); + if (!checked_monotonic_time) { + CheckMonotonicTime(); } if (has_monotonic_time) { #if HAVE_CLOCK_GETTIME - return 1000000000; + return SDL_NS_PER_SECOND; #elif defined(__APPLE__) Uint64 freq = mach_base_info.denom; - freq *= 1000000000; + freq *= SDL_NS_PER_SECOND; freq /= mach_base_info.numer; return freq; #endif } - return 1000000; + return SDL_US_PER_SECOND; } -void SDL_Delay(Uint32 ms) +void SDL_DelayNS(Uint64 ns) { int was_error; #if HAVE_NANOSLEEP - struct timespec elapsed, tv; + struct timespec tv, remaining; #else struct timeval tv; Uint64 then, now, elapsed; @@ -193,36 +151,36 @@ void SDL_Delay(Uint32 ms) #ifdef __EMSCRIPTEN__ if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) { /* pseudo-synchronous pause, used directly or through e.g. SDL_WaitEvent */ - emscripten_sleep(ms); + emscripten_sleep(ns / SDL_NS_PER_MS); return; } #endif /* Set the timeout interval */ #if HAVE_NANOSLEEP - elapsed.tv_sec = ms / 1000; - elapsed.tv_nsec = (ms % 1000) * 1000000; + remaining.tv_sec = (ns / SDL_NS_PER_SECOND); + remaining.tv_nsec = (ns % SDL_NS_PER_SECOND); #else - then = SDL_GetTicks64(); + then = SDL_GetTicksNS(); #endif do { errno = 0; #if HAVE_NANOSLEEP - tv.tv_sec = elapsed.tv_sec; - tv.tv_nsec = elapsed.tv_nsec; - was_error = nanosleep(&tv, &elapsed); + tv.tv_sec = remaining.tv_sec; + tv.tv_nsec = remaining.tv_nsec; + was_error = nanosleep(&tv, &remaining); #else /* Calculate the time interval left (in case of interrupt) */ - now = SDL_GetTicks64(); + now = SDL_GetTicksNS(); elapsed = (now - then); then = now; - if (elapsed >= ((Uint64)ms)) { + if (elapsed >= ns) { break; } - ms -= (Uint32)elapsed; - tv.tv_sec = ms / 1000; - tv.tv_usec = (ms % 1000) * 1000; + ns -= elapsed; + tv.tv_sec = (ns / SDL_NS_PER_SECOND) + tv.tv_usec = SDL_NS_TO_US(ns % SDL_NS_PER_SECOND); was_error = select(0, NULL, NULL, NULL, &tv); #endif /* HAVE_NANOSLEEP */ diff --git a/src/timer/vita/SDL_systimer.c b/src/timer/vita/SDL_systimer.c index 51f883fde..af8d5d16b 100644 --- a/src/timer/vita/SDL_systimer.c +++ b/src/timer/vita/SDL_systimer.c @@ -28,36 +28,6 @@ #include #include -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 SDL_GetPerformanceCounter(void) @@ -68,16 +38,16 @@ SDL_GetPerformanceCounter(void) Uint64 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; - if (ms > max_delay) { - ms = max_delay; + const Uint64 max_delay = 0xffffffff * SDL_NS_PER_US; + if (ns > max_delay) { + ns = max_delay; } - sceKernelDelayThreadCB(ms * 1000); + sceKernelDelayThreadCB((SceUInt)SDL_NS_TO_US(ns)); } #endif /* SDL_TIMER_VITA */ diff --git a/src/timer/windows/SDL_systimer.c b/src/timer/windows/SDL_systimer.c index b5190e83d..e481ae742 100644 --- a/src/timer/windows/SDL_systimer.c +++ b/src/timer/windows/SDL_systimer.c @@ -23,99 +23,7 @@ #ifdef SDL_TIMER_WINDOWS #include "../../core/windows/SDL_windows.h" -#include -/* 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 SDL_GetPerformanceCounter(void) @@ -135,7 +43,7 @@ SDL_GetPerformanceFrequency(void) 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. * @@ -155,7 +63,7 @@ void SDL_Delay(Uint32 ms) HANDLE timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); if (timer) { 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)) { WaitForSingleObject(timer, INFINITE); } @@ -163,19 +71,23 @@ void SDL_Delay(Uint32 ms) return; } #endif -#if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723) - static HANDLE mutex = 0; - if (!mutex) { - mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS); - } - WaitForSingleObjectEx(mutex, ms, FALSE); -#else - if (!ticks_started) { - SDL_TicksInit(); - } - Sleep(ms); + { + 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) + static HANDLE mutex = 0; + if (!mutex) { + mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS); + } + WaitForSingleObjectEx(mutex, (DWORD)SDL_NS_TO_MS(ns), FALSE); +#else + Sleep((DWORD)SDL_NS_TO_MS(ns)); #endif + } } #endif /* SDL_TIMER_WINDOWS */ diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 3ebc6eec9..29bad4ef8 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -294,7 +294,7 @@ struct SDL_VideoDevice /* * Event manager functions */ - int (*WaitEventTimeout)(_THIS, int timeout); + int (*WaitEventTimeout)(_THIS, Sint64 timeoutNS); void (*SendWakeupEvent)(_THIS, SDL_Window *window); void (*PumpEvents)(_THIS); diff --git a/src/video/cocoa/SDL_cocoaevents.h b/src/video/cocoa/SDL_cocoaevents.h index d311800b5..8bd1493db 100644 --- a/src/video/cocoa/SDL_cocoaevents.h +++ b/src/video/cocoa/SDL_cocoaevents.h @@ -25,7 +25,7 @@ extern void Cocoa_RegisterApp(void); 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_SuspendScreenSaver(_THIS); diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index 6c75ddb9f..09e2d5976 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -523,13 +523,13 @@ int Cocoa_PumpEventsUntilDate(_THIS, NSDate *expiration, bool accumulate) return 1; } -int Cocoa_WaitEventTimeout(_THIS, int timeout) +int Cocoa_WaitEventTimeout(_THIS, Sint64 timeoutNS) { @autoreleasepool { - if (timeout > 0) { - NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow:(double)timeout / 1000.0]; + if (timeoutNS > 0) { + NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow:(double)timeoutNS / SDL_NS_PER_SECOND]; return Cocoa_PumpEventsUntilDate(_this, limitDate, false); - } else if (timeout == 0) { + } else if (timeoutNS == 0) { return Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], false); } else { while (Cocoa_PumpEventsUntilDate(_this, [NSDate distantFuture], false) == 0) { diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m index 94a0124c5..16aab89d5 100644 --- a/src/video/cocoa/SDL_cocoaopengl.m +++ b/src/video/cocoa/SDL_cocoaopengl.m @@ -500,7 +500,7 @@ int Cocoa_GL_SwapWindow(_THIS, SDL_Window *window) 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 threads try to swap at the same time, so put a mutex around it. */ diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index c4f7e8350..d4e80eb08 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -252,7 +252,7 @@ @end -static Uint32 s_moveHack; +static Uint64 s_moveHack; 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; NSWindow *nswindow = windata.nswindow; NSRect rect; - Uint32 moveHack; + Uint64 moveHack; rect.origin.x = window->x; rect.origin.y = window->y; @@ -1919,7 +1919,7 @@ void Cocoa_SetWindowSize(_THIS, SDL_Window *window) SDL_WindowData *windata = (__bridge SDL_WindowData *)window->driverdata; NSWindow *nswindow = windata.nswindow; NSRect rect; - Uint32 moveHack; + Uint64 moveHack; /* Cocoa will resize the window from the bottom-left rather than the * top-left when -[nswindow setContentSize:] is used, so we must set the diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c index 6d3467979..8c2f6adc5 100644 --- a/src/video/wayland/SDL_waylanddatamanager.c +++ b/src/video/wayland/SDL_waylanddatamanager.c @@ -37,7 +37,7 @@ /* 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 (!) */ -#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) { @@ -49,7 +49,7 @@ static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_ sigset_t old_sig_set; 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); 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; 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) { bytes_read = SDL_SetError("Pipe timeout"); diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 3ee8cb014..ae2fff421 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -270,7 +270,7 @@ static int dispatch_queued_events(SDL_VideoData *viddata) return ret >= 0 ? 1 : ret; } -int Wayland_WaitEventTimeout(_THIS, int timeout) +int Wayland_WaitEventTimeout(_THIS, Sint64 timeoutNS) { SDL_VideoData *d = _this->driverdata; 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 (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)) { /* A repeat key event was already due */ return 1; } else { uint32_t next_repeat_wait_time = (input->keyboard_repeat.next_repeat_ms - elapsed) + 1; - if (timeout >= 0) { - timeout = SDL_min(timeout, next_repeat_wait_time); + if (timeoutNS >= 0) { + timeoutNS = SDL_min(timeoutNS, SDL_MS_TO_NS(next_repeat_wait_time)); } else { - timeout = next_repeat_wait_time; + timeoutNS = SDL_MS_TO_NS(next_repeat_wait_time); } 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 (WAYLAND_wl_display_prepare_read(d->display) == 0) { /* 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) { /* There are new events available to read */ 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_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)) { return 1; } @@ -375,7 +375,7 @@ void Wayland_PumpEvents(_THIS) err = WAYLAND_wl_display_dispatch_pending(d->display); 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); } diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index c456d8987..de1c8ac7b 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -76,7 +76,7 @@ typedef struct SDL_bool is_key_down; uint32_t key; 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 scancode; char text[8]; @@ -148,7 +148,7 @@ struct SDL_WaylandInput extern void Wayland_PumpEvents(_THIS); 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_primary_selection_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version); diff --git a/src/video/wayland/SDL_waylandopengles.c b/src/video/wayland/SDL_waylandopengles.c index 5c20a1a80..d7f0b3f80 100644 --- a/src/video/wayland/SDL_waylandopengles.c +++ b/src/video/wayland/SDL_waylandopengles.c @@ -125,9 +125,9 @@ int Wayland_GLES_SwapWindow(_THIS, SDL_Window *window) struct wl_display *display = videodata->display; SDL_VideoDisplay *sdldisplay = SDL_GetDisplayForWindow(window); /* ~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) { - Uint32 now; + Uint64 now; 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() */ - now = SDL_GetTicks(); - if (SDL_TICKS_PASSED(now, max_wait)) { + now = SDL_GetTicksNS(); + if (now >= max_wait) { /* Timeout expired. Cancel the read. */ WAYLAND_wl_display_cancel_read(display); break; diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 3e4095427..8ae2b4c1d 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1707,8 +1707,8 @@ static void WIN_UpdateClipCursorForWindows() { SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_Window *window; - Uint32 now = SDL_GetTicks(); - const Uint32 CLIPCURSOR_UPDATE_INTERVAL_MS = 3000; + Uint64 now = SDL_GetTicks(); + const int CLIPCURSOR_UPDATE_INTERVAL_MS = 3000; if (_this) { for (window = _this->windows; window; window = window->next) { @@ -1717,7 +1717,7 @@ static void WIN_UpdateClipCursorForWindows() if (data->skip_update_clipcursor) { data->skip_update_clipcursor = SDL_FALSE; 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); } } @@ -1765,17 +1765,17 @@ void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata) g_WindowsMessageHookData = userdata; } -int WIN_WaitEventTimeout(_THIS, int timeout) +int WIN_WaitEventTimeout(_THIS, Sint64 timeoutNS) { MSG msg; if (g_WindowsEnableMessageLoop) { BOOL message_result; UINT_PTR timer_id = 0; - if (timeout > 0) { - timer_id = SetTimer(NULL, 0, timeout, NULL); + if (timeoutNS > 0) { + timer_id = SetTimer(NULL, 0, (UINT)SDL_NS_TO_MS(timeoutNS), NULL); message_result = GetMessage(&msg, 0, 0, 0); KillTimer(NULL, timer_id); - } else if (timeout == 0) { + } else if (timeoutNS == 0) { message_result = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); } else { 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); } +/* Used to compare Windows message timestamps */ +#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0) + void WIN_PumpEvents(_THIS) { MSG msg; diff --git a/src/video/windows/SDL_windowsevents.h b/src/video/windows/SDL_windowsevents.h index 4d7a61072..b68fc33da 100644 --- a/src/video/windows/SDL_windowsevents.h +++ b/src/video/windows/SDL_windowsevents.h @@ -32,7 +32,7 @@ extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); extern void WIN_PumpEvents(_THIS); 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_ */ diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 7f3aa6aa4..e5df761ad 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -55,7 +55,7 @@ typedef struct SDL_bool in_title_click; Uint8 focus_click_pending; SDL_bool skip_update_clipcursor; - Uint32 last_updated_clipcursor; + Uint64 last_updated_clipcursor; SDL_bool mouse_relative_mode_center; SDL_bool windowed_mode_was_maximized; SDL_bool in_window_deactivation; diff --git a/src/video/x11/SDL_x11clipboard.c b/src/video/x11/SDL_x11clipboard.c index f717331c9..515c8fa79 100644 --- a/src/video/x11/SDL_x11clipboard.c +++ b/src/video/x11/SDL_x11clipboard.c @@ -151,8 +151,8 @@ static char *GetSlectionText(_THIS, Atom selection_type) unsigned long overflow; unsigned char *src; char *text; - Uint32 waitStart; - Uint32 waitElapsed; + Uint64 waitStart; + Uint64 waitElapsed; text = NULL; diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 7778203cb..5e1f9dbd1 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1338,7 +1338,7 @@ static void X11_DispatchEvent(_THIS, XEvent *xevent) } if (data->last_focus_event_time) { 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); } data->last_focus_event_time = 0; @@ -1577,8 +1577,8 @@ static void X11_HandleFocusChanges(_THIS) for (i = 0; i < videodata->numwindows; ++i) { SDL_WindowData *data = videodata->windowlist[i]; if (data && data->pending_focus != PENDING_FOCUS_NONE) { - Uint32 now = SDL_GetTicks(); - if (SDL_TICKS_PASSED(now, data->pending_focus_time)) { + Uint64 now = SDL_GetTicks(); + if (now >= data->pending_focus_time) { if (data->pending_focus == PENDING_FOCUS_IN) { X11_DispatchFocusIn(_this, data); } else { @@ -1625,7 +1625,7 @@ void X11_SendWakeupEvent(_THIS, SDL_Window *window) X11_XFlush(req_display); } -int X11_WaitEventTimeout(_THIS, int timeout) +int X11_WaitEventTimeout(_THIS, Sint64 timeoutNS) { SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; Display *display; @@ -1638,11 +1638,11 @@ int X11_WaitEventTimeout(_THIS, int timeout) X11_XFlush(display); if (X11_PollEvent(display, &xevent)) { /* Fall through */ - } else if (timeout == 0) { + } else if (timeoutNS == 0) { return 0; } else { /* 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 (!X11_PollEvent(display, &xevent)) { /* Someone may have beat us to reading the fd. Return 1 here to @@ -1682,16 +1682,15 @@ void X11_PumpEvents(_THIS) int i; 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. */ } } /* Update activity every 30 seconds to prevent screensaver */ if (_this->suspend_screensaver) { - const Uint32 now = SDL_GetTicks(); - if (!data->screensaver_activity || - SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) { + Uint64 now = SDL_GetTicks(); + if (!data->screensaver_activity || now >= (data->screensaver_activity + 30000)) { X11_XResetScreenSaver(data->display); #if SDL_USE_LIBDBUS @@ -1722,7 +1721,7 @@ void X11_PumpEvents(_THIS) for (i = 0; i < data->numwindows; ++i) { if (data->windowlist[i] != NULL && 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); } } diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h index 6fe0ad3ab..c82b20c58 100644 --- a/src/video/x11/SDL_x11events.h +++ b/src/video/x11/SDL_x11events.h @@ -24,7 +24,7 @@ #define SDL_x11events_h_ 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_SuspendScreenSaver(_THIS); extern void X11_ReconcileKeyboardState(_THIS); diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 47e03e9b8..33e98d346 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -71,7 +71,7 @@ typedef struct SDL_VideoData char *classname; pid_t pid; XIM im; - Uint32 screensaver_activity; + Uint64 screensaver_activity; int numwindows; SDL_WindowData **windowlist; int windowlistlength; @@ -126,7 +126,7 @@ typedef struct SDL_VideoData 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_Point global_mouse_position; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index c5210ebfb..72066d9d6 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -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) { - Uint32 start = SDL_GetTicks(); + Uint64 start = SDL_GetTicks(); while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) { - if (SDL_TICKS_PASSED(SDL_GetTicks(), start + timeoutMS)) { + if (SDL_GetTicks() >= (start + timeoutMS)) { return False; } } @@ -797,7 +797,7 @@ void X11_SetWindowPosition(_THIS, SDL_Window *window) Window *children; XWindowAttributes attrs; int orig_x, orig_y; - Uint32 timeout; + Uint64 timeout; X11_XSync(display, False); 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; } @@ -907,7 +907,7 @@ void X11_SetWindowSize(_THIS, SDL_Window *window) int (*prev_handler)(Display *, XErrorEvent *) = NULL; XWindowAttributes attrs; int orig_w, orig_h; - Uint32 timeout; + Uint64 timeout; X11_XSync(display, False); 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; } @@ -1377,7 +1377,7 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis X11_XSync(display, False); prev_handler = X11_XSetErrorHandler(X11_CatchAnyError); - timeout = SDL_GetTicks64() + 100; + timeout = SDL_GetTicks() + 100; while (SDL_TRUE) { 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; } @@ -1720,9 +1720,6 @@ int X11_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation) 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 */ data->flash_cancel_time = SDL_GetTicks() + 1000; - if (!data->flash_cancel_time) { - data->flash_cancel_time = 1; - } } break; case SDL_FLASH_UNTIL_FOCUSED: diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 01e4e4f9a..18e548303 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -60,16 +60,16 @@ typedef struct int border_top; int border_bottom; SDL_bool mouse_grabbed; - Uint32 last_focus_event_time; + Uint64 last_focus_event_time; PendingFocusEnum pending_focus; - Uint32 pending_focus_time; + Uint64 pending_focus_time; XConfigureEvent last_xconfigure; struct SDL_VideoData *videodata; unsigned long user_time; Atom xdnd_req; Window xdnd_source; SDL_bool flashing_window; - Uint32 flash_cancel_time; + Uint64 flash_cancel_time; #if SDL_VIDEO_OPENGL_EGL EGLSurface egl_surface; #endif diff --git a/test/controllermap.c b/test/controllermap.c index ed28697c6..22c5715ed 100644 --- a/test/controllermap.c +++ b/test/controllermap.c @@ -164,7 +164,7 @@ static int s_nNumAxes; static AxisState *s_arrAxisState; static int s_iCurrentBinding; -static Uint32 s_unPendingAdvanceTime; +static Uint64 s_unPendingAdvanceTime; static SDL_bool s_bBindingComplete; static SDL_Window *window; @@ -354,7 +354,7 @@ WatchJoystick(SDL_Joystick *joystick) SDL_Event event; SDL_Rect dst; Uint8 alpha = 200, alpha_step = -1; - Uint32 alpha_ticks = 0; + Uint64 alpha_ticks = 0; SDL_JoystickID nJoystickID; background_front = LoadTexture(screen, "controllermap.bmp", SDL_FALSE, NULL, NULL); @@ -409,7 +409,7 @@ WatchJoystick(SDL_Joystick *joystick) dst.y = s_arrBindingDisplay[iElement].y; 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 += alpha_step; if (alpha == 255) { diff --git a/test/testatomic.c b/test/testatomic.c index c194db2fd..a81b6117b 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -127,10 +127,10 @@ static int SDLCALL adder(void *junk) static void runAdder(void) { - Uint32 start, end; + Uint64 start, end; int T = NThreads; - start = SDL_GetTicks(); + start = SDL_GetTicksNS(); threadDone = SDL_CreateSemaphore(0); @@ -146,9 +146,9 @@ static void runAdder(void) 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() @@ -585,7 +585,7 @@ static void RunFIFOTest(SDL_bool lock_free) SDL_Thread *fifo_thread = NULL; WriterData writerData[NUM_WRITERS]; ReaderData readerData[NUM_READERS]; - Uint32 start, end; + Uint64 start, end; int i, j; int grand_total; char textBuffer[1024]; @@ -601,7 +601,7 @@ static void RunFIFOTest(SDL_bool lock_free) queue.mutex = SDL_CreateMutex(); } - start = SDL_GetTicks(); + start = SDL_GetTicksNS(); #ifdef TEST_SPINLOCK_FIFO /* Start a monitoring thread */ @@ -646,7 +646,7 @@ static void RunFIFOTest(SDL_bool lock_free) SDL_WaitThread(readerData[i].thread, NULL); } - end = SDL_GetTicks(); + end = SDL_GetTicksNS(); /* Wait for the FIFO thread */ if (fifo_thread) { @@ -657,7 +657,7 @@ static void RunFIFOTest(SDL_bool lock_free) 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"); for (i = 0; i < NUM_WRITERS; ++i) { diff --git a/test/testautomation_timer.c b/test/testautomation_timer.c index 25a180b83..cf61de6d4 100644 --- a/test/testautomation_timer.c +++ b/test/testautomation_timer.c @@ -61,11 +61,11 @@ int timer_getPerformanceFrequency(void *arg) */ int timer_delayAndGetTicks(void *arg) { - const Uint32 testDelay = 100; - const Uint32 marginOfError = 25; - Uint32 result; - Uint32 result2; - Uint32 difference; + const int testDelay = 100; + const int marginOfError = 25; + Uint64 result; + Uint64 result2; + Sint64 difference; /* Zero delay */ SDL_Delay(0); @@ -81,17 +81,17 @@ int timer_delayAndGetTicks(void *arg) /* Get ticks count - should be non-zero by now */ result = 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 */ SDL_Delay(testDelay); - SDLTest_AssertPass("Call to SDL_Delay(%" SDL_PRIu32 ")", testDelay); + SDLTest_AssertPass("Call to SDL_Delay(%d)", testDelay); result2 = 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; - SDLTest_AssertCheck(difference > (testDelay - marginOfError), "Check difference, expected: >%" SDL_PRIu32 ", got: %" SDL_PRIu32, 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); + SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%d, got: %" SDL_PRIu64, testDelay + marginOfError, difference); return TEST_COMPLETED; } diff --git a/test/testdraw2.c b/test/testdraw2.c index d30ac3789..2ff9e4f84 100644 --- a/test/testdraw2.c +++ b/test/testdraw2.c @@ -31,8 +31,9 @@ static int cycle_direction = 1; static int current_alpha = 255; static int current_color = 255; static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE; -static Uint32 next_fps_check, frames; -static const Uint32 fps_check_delay = 5000; +static Uint64 next_fps_check; +static Uint32 frames; +static const int fps_check_delay = 5000; int done; @@ -175,7 +176,7 @@ void DrawRects(SDL_Renderer *renderer) void loop() { - Uint32 now; + Uint64 now; int i; SDL_Event event; @@ -204,9 +205,9 @@ void loop() #endif frames++; now = SDL_GetTicks(); - if (SDL_TICKS_PASSED(now, next_fps_check)) { + if (now >= next_fps_check) { /* 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); SDL_Log("%2.2f frames per second\n", fps); next_fps_check = now + fps_check_delay; diff --git a/test/testgeometry.c b/test/testgeometry.c index 09df8478e..afe71740f 100644 --- a/test/testgeometry.c +++ b/test/testgeometry.c @@ -164,7 +164,8 @@ int main(int argc, char *argv[]) { int i; const char *icon = "icon.bmp"; - Uint32 then, now, frames; + Uint64 then, now; + Uint32 frames; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); diff --git a/test/testgl2.c b/test/testgl2.c index b5fc31f07..238a1fef9 100644 --- a/test/testgl2.c +++ b/test/testgl2.c @@ -203,7 +203,8 @@ int main(int argc, char *argv[]) int i, done; SDL_DisplayMode mode; SDL_Event event; - Uint32 then, now, frames; + Uint64 then, now; + Uint32 frames; int status; int dw, dh; int swap_interval = 0; diff --git a/test/testgles2.c b/test/testgles2.c index 188f6fd30..7e047b21d 100644 --- a/test/testgles2.c +++ b/test/testgles2.c @@ -615,7 +615,7 @@ int main(int argc, char *argv[]) int value; int i; SDL_DisplayMode mode; - Uint32 then, now; + Uint64 then, now; int status; shader_data *data; diff --git a/test/testgles2_sdf.c b/test/testgles2_sdf.c index 804aa499b..edae4ef7a 100644 --- a/test/testgles2_sdf.c +++ b/test/testgles2_sdf.c @@ -434,7 +434,7 @@ int main(int argc, char *argv[]) int value; int i; SDL_DisplayMode mode; - Uint32 then, now; + Uint64 then, now; int status; shader_data *data; char *path = NULL; diff --git a/test/testintersections.c b/test/testintersections.c index 06207d0c9..94966b2a3 100644 --- a/test/testintersections.c +++ b/test/testintersections.c @@ -278,7 +278,8 @@ void loop() int main(int argc, char *argv[]) { int i; - Uint32 then, now, frames; + Uint64 then, now; + Uint32 frames; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); diff --git a/test/testoffscreen.c b/test/testoffscreen.c index f97337d94..833e36c17 100644 --- a/test/testoffscreen.c +++ b/test/testoffscreen.c @@ -93,7 +93,8 @@ void loop() int main(int argc, char *argv[]) { #ifndef __EMSCRIPTEN__ - Uint32 then, now, frames; + Uint64 then, now; + Uint32 frames; #endif /* Enable standard application logging */ diff --git a/test/testrendercopyex.c b/test/testrendercopyex.c index 7aaf870ca..a6f2ec9f3 100644 --- a/test/testrendercopyex.c +++ b/test/testrendercopyex.c @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) { int i; int frames; - Uint32 then, now; + Uint64 then, now; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); diff --git a/test/testrendertarget.c b/test/testrendertarget.c index 35c0219c4..1e0adca48 100644 --- a/test/testrendertarget.c +++ b/test/testrendertarget.c @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) { int i; int frames; - Uint32 then, now; + Uint64 then, now; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); diff --git a/test/testscale.c b/test/testscale.c index 2a2041018..8398bdcfa 100644 --- a/test/testscale.c +++ b/test/testscale.c @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) { int i; int frames; - Uint32 then, now; + Uint64 then, now; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); diff --git a/test/testsem.c b/test/testsem.c index 26cbf261d..e3a8ba217 100644 --- a/test/testsem.c +++ b/test/testsem.c @@ -98,9 +98,9 @@ TestRealWorld(int init_sem) static void TestWaitTimeout(void) { - Uint32 start_ticks; - Uint32 end_ticks; - Uint32 duration; + Uint64 start_ticks; + Uint64 end_ticks; + Uint64 duration; int retval; sem = SDL_CreateSemaphore(0); @@ -114,7 +114,7 @@ TestWaitTimeout(void) /* Accept a little offset in the effective wait */ 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 */ if (retval != SDL_MUTEX_TIMEDOUT) { @@ -127,9 +127,9 @@ TestWaitTimeout(void) static void TestOverheadUncontended(void) { - Uint32 start_ticks; - Uint32 end_ticks; - Uint32 duration; + Uint64 start_ticks; + Uint64 end_ticks; + Uint64 duration; int i, j; sem = SDL_CreateSemaphore(0); @@ -147,7 +147,7 @@ TestOverheadUncontended(void) end_ticks = SDL_GetTicks(); 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); } @@ -179,9 +179,9 @@ ThreadFuncOverheadContended(void *data) static void TestOverheadContended(SDL_bool try_wait) { - Uint32 start_ticks; - Uint32 end_ticks; - Uint32 duration; + Uint64 start_ticks; + Uint64 end_ticks; + Uint64 duration; Thread_State thread_states[NUM_THREADS] = { { 0 } }; char textBuffer[1024]; 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); 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, loop_count, ((float)content_count * 100) / loop_count); /* Print how many semaphores where consumed per thread */ diff --git a/test/testsprite2.c b/test/testsprite2.c index 8f9904be2..a7414e742 100644 --- a/test/testsprite2.c +++ b/test/testsprite2.c @@ -37,8 +37,9 @@ static SDL_Rect *positions; static SDL_Rect *velocities; static int sprite_w, sprite_h; static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND; -static Uint32 next_fps_check, frames; -static const Uint32 fps_check_delay = 5000; +static Uint64 next_fps_check; +static Uint32 frames; +static const int fps_check_delay = 5000; static int use_rendergeometry = 0; /* Number of iterations to move sprites - used for visual tests. */ @@ -393,7 +394,7 @@ void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite) void loop() { - Uint32 now; + Uint64 now; int i; SDL_Event event; @@ -415,9 +416,9 @@ void loop() frames++; now = SDL_GetTicks(); - if (SDL_TICKS_PASSED(now, next_fps_check)) { + if (now >= next_fps_check) { /* 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); SDL_Log("%2.2f frames per second\n", fps); next_fps_check = now + fps_check_delay; diff --git a/test/testtimer.c b/test/testtimer.c index 47da551e9..baa34e2d3 100644 --- a/test/testtimer.c +++ b/test/testtimer.c @@ -37,9 +37,8 @@ int main(int argc, char *argv[]) { int i, desired; SDL_TimerID t1, t2, t3; - Uint64 start64, now64; - Uint32 start32, now32; Uint64 start, now; + Uint64 start_perf, now_perf; /* Enable standard application logging */ 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. */ SDL_Log("Sanity-checking GetTicks\n"); for (i = 0; i < 1000; ++i) { - start64 = SDL_GetTicks64(); - start32 = SDL_GetTicks(); + start = SDL_GetTicks(); SDL_Delay(1); - now64 = SDL_GetTicks64() - start64; - now32 = SDL_GetTicks() - start32; - 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, %d ms in ticks64\n", i, (int)now32, (int)now64); + now = SDL_GetTicks() - start; + if (now > 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_Quit(); return 1; } @@ -120,22 +117,20 @@ int main(int argc, char *argv[]) SDL_RemoveTimer(t2); SDL_RemoveTimer(t3); - start = SDL_GetPerformanceCounter(); + start_perf = SDL_GetPerformanceCounter(); for (i = 0; i < 1000000; ++i) { ticktock(0, NULL); } - now = SDL_GetPerformanceCounter(); - SDL_Log("1 million iterations of ticktock took %f ms\n", (double)((now - start) * 1000) / SDL_GetPerformanceFrequency()); + now_perf = SDL_GetPerformanceCounter(); + 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()); - start64 = SDL_GetTicks64(); - start32 = SDL_GetTicks(); - start = SDL_GetPerformanceCounter(); + start = SDL_GetTicks(); + start_perf = SDL_GetPerformanceCounter(); SDL_Delay(1000); - now = SDL_GetPerformanceCounter(); - now64 = SDL_GetTicks64(); - now32 = SDL_GetTicks(); - 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()); + now_perf = SDL_GetPerformanceCounter(); + now = 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_Quit(); return 0; diff --git a/test/testviewport.c b/test/testviewport.c index f4ba414cf..6b9b29481 100644 --- a/test/testviewport.c +++ b/test/testviewport.c @@ -146,7 +146,8 @@ void loop() int main(int argc, char *argv[]) { int i; - Uint32 then, now, frames; + Uint64 then, now; + Uint32 frames; /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); diff --git a/test/testvulkan.c b/test/testvulkan.c index 766d2d9e3..4a618d26d 100644 --- a/test/testvulkan.c +++ b/test/testvulkan.c @@ -1081,7 +1081,8 @@ int main(int argc, char **argv) int done; SDL_DisplayMode mode; SDL_Event event; - Uint32 then, now, frames; + Uint64 then, now; + Uint32 frames; int dw, dh; /* Enable standard application logging */ diff --git a/test/testyuv.c b/test/testyuv.c index 504714217..7ee67d5f2 100644 --- a/test/testyuv.c +++ b/test/testyuv.c @@ -254,7 +254,8 @@ int main(int argc, char **argv) int current = 0; int pitch; Uint8 *raw_yuv; - Uint32 then, now, i, iterations = 100; + Uint64 then, now; + Uint32 i, iterations = 100; SDL_bool should_run_automated_tests = SDL_FALSE; 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); } 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", SDL_WINDOWPOS_UNDEFINED,