Compare commits

..
25 Commits
Author SHA1 Message Date
Qiu Qiang 62639fdf88 Improve camera frame rate matching on macOS
- Prefer formats with narrower frame rate ranges
- Set frame duration on both device and connection
  for better enforcement
2025-12-08 21:03:09 -08:00
Ryan C. Gordon b3cdeb942a opengl: default to vsync=0 everywhere.
This reverts commit 3ee29f2e7a, among other
changes. This means getting a scary warning on the javascript console in
Emscripten by default, but this is easily fixed by setting a GL swap
interval at startup or creating a 2D renderer with the appropriate property
(or call to SDL_SetRenderVSync()).

Fixes #14625.
2025-12-08 15:12:17 -05:00
Anonymous Maarten a296c40867 isfinite is not available on all platforms, so add a bitmasking alternative
Compiler Explorer shows both result in the same assembly.
2025-12-08 20:48:47 +01:00
Anonymous Maarten f896e26f59 tests: find X11 and wayland-client 2025-12-08 20:48:47 +01:00
Anonymous Maarten d19b010d4e cmake: only enable building tests when SDL is the main project 2025-12-08 20:48:47 +01:00
Frank Praznik 14aa5cf762 x11: Remove unused function parameter 2025-12-08 13:15:12 -05:00
Frank Praznik 69255b870d x11: Dedup the X11_FindWindow() function
The was duplicated in the XInput2 code, but taking an SDL_VideoData parameter instead of SDL_VideoDevice. Remove the duplicated XInput2 function, and use an SDL_VideoData parameter for X11_FindWindow to avoid an unnecessary dereference.
2025-12-08 13:15:12 -05:00
Cameron Cawley a4de176e1c Use the correct pixel formats for Vulkan on big endian 2025-12-08 10:07:31 -08:00
Sam Lantinga 9b36a76ee6 Fixed supported pixel formats on big endian systems (thanks @ccawley2011!) 2025-12-08 08:36:32 -08:00
SDL Wiki Bot a75bf983e5 Sync SDL3 wiki -> header
[ci skip]
2025-12-08 16:27:12 +00:00
Ryan C. Gordon 6f774908fe audio: SDL_GetAudioDeviceName() now works with the default device IDs.
Fixes #14615.
2025-12-08 11:25:15 -05:00
Sam Lantinga a35639c7b5 Added patch note for SDL_SetWindowFillDocument() 2025-12-08 08:18:34 -08:00
Sam Lantinga db3ee5d62b Enable building the tests by default
A common use case is asking someone to clone SDL and run a test. This simplifies the instructions so we don't also have to tell them how to enable the tests. Anyone savvy can just add -DSDL_TESTS=OFF if they don't want to have them.
2025-12-08 08:15:12 -08:00
Ryan C. Gordon 08a547e077 WhatsNew.txt: Removed reference to removed property.
Fixes #14623.
2025-12-08 11:03:42 -05:00
SDL Wiki Bot b428c1834f Sync SDL3 wiki -> header
[ci skip]
2025-12-08 03:26:26 +00:00
Ryan C. Gordon 5813d0ec0a surface: SDL_RotateSurface should update SDL_PROP_SURFACE_ROTATION_FLOAT.
Fixes #14616.
2025-12-07 22:25:08 -05:00
Ryan C. Gordon 4194879df1 surface: Surface rotation property should be float, not int.
Adjusted camera internals to work in floats, too.

Reference Issue #14616.
2025-12-07 22:25:08 -05:00
Ryan C. Gordon 9918d6cb5e emscripten: Move fill-document from hint/property to a window flag.
Fixes #14617.
2025-12-07 21:12:13 -05:00
Qiu Qiang 19988c5faa Fix loop variable bug in V4L2 camera format enumeration 2025-12-07 14:11:27 -08:00
Sam Lantinga 7773157fae Updated to version 3.3.5 for development 2025-12-07 09:30:04 -08:00
Sam Lantinga 9bf86a2db3 Added documentation for the 3.4.0 release 2025-12-07 09:18:29 -08:00
Sam Lantinga edb81cf84a Fixed whitespace 2025-12-07 09:12:34 -08:00
SDL Wiki Bot 9257df24b5 Sync SDL3 wiki -> header
[ci skip]
2025-12-07 16:05:39 +00:00
Sam Lantinga 97b0b13147 Fixed subdirectories showing in enumeration of Steam storage 2025-12-06 22:35:05 -08:00
Christian Semmler 7e78636e8e Handle SharedArrayBuffer for PNG data
The Emscripten support for setting window icons introduced in #14490 does not work when using pthreads. Using `SetWindowIcon` will cause the program to crash. The reason for that is that the `Blob` constructor does not accept shared memory (`SharedArrayBuffer`).

We need to create a local copy of the icon data if necessary.
2025-12-06 22:11:55 -08:00
49 changed files with 370 additions and 200 deletions

No files matched your search

+2 -2
View File
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
endif()
# See docs/release_checklist.md
project(SDL3 LANGUAGES C VERSION "3.3.4")
project(SDL3 LANGUAGES C VERSION "3.3.5")
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(SDL3_MAINPROJECT ON)
@@ -393,7 +393,7 @@ cmake_dependent_option(SDL_SHARED "Build a shared version of the library" ${SDL_
cmake_dependent_option(SDL_STATIC "Build a static version of the library" ${SDL_STATIC_DEFAULT} ${SDL_STATIC_AVAILABLE} OFF)
option(SDL_TEST_LIBRARY "Build the SDL3_test library" ON)
dep_option(SDL_TESTS "Build the test directory" OFF SDL_TEST_LIBRARY OFF)
dep_option(SDL_TESTS "Build the test directory" ${SDL3_MAINPROJECT} SDL_TEST_LIBRARY OFF)
dep_option(SDL_INSTALL_TESTS "Install test-cases" OFF "SDL_INSTALL;NOT SDL_FRAMEWORK" OFF)
dep_option(SDL_TESTS_LINK_SHARED "link tests to shared SDL library" "${SDL_SHARED}" "SDL_SHARED;SDL_STATIC" "${SDL_SHARED}")
set(SDL_TESTS_TIMEOUT_MULTIPLIER "1" CACHE STRING "Timeout multiplier to account for really slow machines")
+54 -2
View File
@@ -8,43 +8,95 @@ This is a list of major changes in SDL's version history.
General:
* Added SDL_CreateAnimatedCursor() to create animated color cursors
* Added SDL_SetWindowProgressState(), SDL_SetWindowProgressValue(), SDL_GetWindowProgressState(), and SDL_GetWindowProgressValue() to show progress in the window's taskbar icon on Windows and Linux
* Added SDL_GetGPUDeviceProperties() to get the properties of an SDL GPU device
* Added GPU device creation properties to enable the GPU API on older hardware if you're not using these features:
- SDL_PROP_GPU_DEVICE_CREATE_FEATURE_CLIP_DISTANCE_BOOLEAN
- SDL_PROP_GPU_DEVICE_CREATE_FEATURE_DEPTH_CLAMPING_BOOLEAN
- SDL_PROP_GPU_DEVICE_CREATE_FEATURE_INDIRECT_DRAW_FIRST_INSTANCE_BOOLEAN
- SDL_PROP_GPU_DEVICE_CREATE_FEATURE_ANISOTROPY_BOOLEAN
- SDL_PROP_GPU_DEVICE_CREATE_D3D12_ALLOW_FEWER_RESOURCE_SLOTS_BOOLEAN
* Added SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER to enable configuring Vulkan features when creating a GPU device
* Added SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION_BOOLEAN to allow requiring Vulkan hardware acceleration when creating a GPU device
* Added SDL_GetGPUDeviceProperties() to query information from a GPU device:
- SDL_PROP_GPU_DEVICE_NAME_STRING
- SDL_PROP_GPU_DEVICE_DRIVER_NAME_STRING
- SDL_PROP_GPU_DEVICE_DRIVER_VERSION_STRING
- SDL_PROP_GPU_DEVICE_DRIVER_INFO_STRING
* Added SDL_GetPixelFormatFromGPUTextureFormat() and SDL_GetGPUTextureFormatFromPixelFormat()
* Added SDL_CreateGPURenderer() and SDL_GetGPURendererDevice() to create a 2D renderer for use with GPU rendering.
* Added SDL_CreateGPURenderState(), SDL_SetGPURenderStateFragmentUniforms(), SDL_SetGPURenderState(), and SDL_DestroyGPURenderState() to use fragment shaders with a GPU 2D renderer
* Added SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER to create a 2D texture from an existing GPU texture
* Added SDL_PROP_TEXTURE_GPU_TEXTURE_POINTER to get the GPU texture from a 2D texture when using the GPU 2D renderer
* Added support for YUV textures and HDR colorspaces to the GPU 2D renderer
* Added support for textures with palettes, and SDL_GetTexturePalette() and SDL_SetTexturePalette() to interact with them
* Added SDL_RenderTexture9GridTiled() to do tiled instead of stretched 9-grid texture rendering
* Added SDL_GetDefaultTextureScaleMode() and SDL_SetDefaultTextureScaleMode() to set the texture scale mode for new textures
* Added SDL_GetRenderTextureAddressMode() and SDL_SetRenderTextureAddressMode() to change the texture addressing mode
* Added SDL_TEXTURE_ADDRESS_WRAP to allow wrapping of textures if the renderer has SDL_PROP_RENDERER_TEXTURE_WRAPPING_BOOLEAN set
* The default YUV colorspace is BT.601 limited range, for compatibility with SDL2
* Added SDL_SCALEMODE_PIXELART as an improved scaling algorithm for pixel art without introducing blurring
* Added SDL_FLIP_HORIZONTAL_AND_VERTICAL to flip a surface both horizontally and vertically
* Added SDL_LoadPNG(), SDL_LoadPNG_IO(), SDL_SavePNG(), and SDL_SavePNG_IO() to load and save PNG images
* Added SDL_LoadSurface() and SDL_LoadSurface_IO() to detect BMP and PNG formats and load them as surfaces
* Added SDL_PROP_SURFACE_ROTATION_FLOAT to indicate the rotation needed to display camera images upright
* Added SDL_RotateSurface() to create a rotated copy of a surface
* SDL_EVENT_WINDOW_EXPOSED now sets data1 to true if it is sent during live resizing
* Added SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, which is sent when the usable desktop bounds change
* Added SDL_EVENT_SCREEN_KEYBOARD_SHOWN, which is sent when the on-screen keyboard has been shown
* Added SDL_EVENT_SCREEN_KEYBOARD_HIDDEN, which is sent when the on-screen keyboard has been hidden
* Added pinch gesture events: SDL_EVENT_PINCH_BEGIN, SDL_EVENT_PINCH_UPDATE, SDL_EVENT_PINCH_END
* SDL_EVENT_AUDIO_DEVICE_ADDED will be sent during initialization for each audio device
* SDL_GetCameraPermissionState() returns SDL_CameraPermissionState instead of int
* Added SDL_PutAudioStreamDataNoCopy() to do more efficient audio stream processing in some cases
* Added SDL_PutAudioStreamPlanarData() to add planar audio data instead of interleaved data to an audio stream
* Added SDL_HINT_AUDIO_DEVICE_RAW_STREAM to signal that the OS shouldn't do further audio processing, useful for applications that handle noise canceling, etc.
* Added SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN to allow streams that persist beyond the audio subsystem lifetime.
* Added enhanced support for 8BitDo controllers
* Added enhanced support for FlyDigi controllers
* Added enhanced support for Hand Held Legend SInput controllers
* Added support for wired Nintendo Switch 2 controllers when built with libusb
* Added SDL_hid_get_properties() to associate SDL properties with HID devices
* Added SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER to query the libusb handle from an SDL_hid_device, if it's been opened with libusb
* Added SDL_SetRelativeMouseTransform() to add custom mouse input transformation
* Added SDL_GetPenDeviceType() to determine whether a pen is on the screen or on a separate touchpad
* SDL_HINT_MAIN_CALLBACK_RATE may be set to a floating point callback rate
* Added SDL_GetEventDescription() to get an English description of an event, suitable for logging
* Added SDL_PROP_IOSTREAM_MEMORY_FREE_FUNC_POINTER to allow custom freeing of the memory used by SDL_IOFromMem() and SDL_IOFromConstMem()
* Added SDL_PROP_PROCESS_CREATE_WORKING_DIRECTORY_STRING to set the working directory for new processes
* Added verbose log output when the DEBUG_INVOCATION environment variable is set to "1"
* Added SDL_AddAtomicU32()
* Added SDL_GetSystemPageSize() to get the system page size
* Added SDL_ALIGNED() to signal that data should have a specific alignment
Windows:
* Added SDL_HINT_RENDER_DIRECT3D11_WARP to enable D3D11 software rasterization
* Using SDL_InsertGPUDebugLabel(), SDL_PushGPUDebugGroup(), and SDL_PopGPUDebugGroup() requires WinPixEventRuntime.dll to be in your PATH or in the same directory as your executable
* Added SDL_PROP_DISPLAY_WINDOWS_HMONITOR_POINTER so you can query the HMONITOR associated with a display
* SDL_HINT_AUDIO_DEVICE_STREAM_ROLE is used by the WASAPI audio driver to set the audio stream category
* Added SDL_HINT_AUDIO_DEVICE_RAW_STREAM to signal whether the OS audio driver should do additional signal processing
* Added SDL_HINT_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS to allow disabling some system hotkeys when in raw input mode
* SDL_HINT_WINDOWS_GAMEINPUT is disabled by default
macOS:
* Added SDL_HINT_MAC_PRESS_AND_HOLD to control whether holding down a key will repeat the pressed key or open the accents menu
Linux:
* Added atomic support for KMSDRM
* Added SDL_HINT_KMSDRM_ATOMIC to control whether KMSDRM will use atomic functionality
* Added SDL_PROP_DISPLAY_WAYLAND_WL_OUTPUT_POINTER so you can query the wl_output associated with a display
Emscripten:
* Added SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT for applications that don't want to be fullscreen, but would like to fill the window
* Added SDL_WINDOW_FILL_DOCUMENT to indicate that windows expand to fill the whole browser window
* Added SDL_SetWindowFillDocument() to change whether windows expand to fill the whole browser window
* Added SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_CANVAS_ID_STRING to allow setting the SDL canvas ID, and SDL_PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING to query it on existing windows
* Added SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING to specify where keyboard input is bound, and SDL_PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING to query it on existing windows
iOS:
* SDL now supports window scenes, fixing the warning "CLIENT OF UIKIT REQUIRES UPDATE"
* Added SDL_PROP_WINDOW_CREATE_WINDOWSCENE_POINTER to specify the window scene for a window
visionOS:
* The default refresh rate has been increased to 90Hz
* SDL_SetWindowSize() changes the size of the window on Vision Pro headsets
PlayStation 2:
* Added the following hints to control the display parameters: SDL_HINT_PS2_GS_WIDTH, SDL_HINT_PS2_GS_HEIGHT, SDL_HINT_PS2_GS_PROGRESSIVE, SDL_HINT_PS2_GS_MODE
+2 -2
View File
@@ -19,10 +19,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.3.4</string>
<string>3.3.5</string>
<key>CFBundleSignature</key>
<string>SDLX</string>
<key>CFBundleVersion</key>
<string>3.3.4</string>
<string>3.3.5</string>
</dict>
</plist>
+6 -6
View File
@@ -3145,8 +3145,8 @@
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
DEPLOYMENT_POSTPROCESSING = YES;
DYLIB_COMPATIBILITY_VERSION = 305.0.0;
DYLIB_CURRENT_VERSION = 305.0.0;
DYLIB_COMPATIBILITY_VERSION = 306.0.0;
DYLIB_CURRENT_VERSION = 306.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
@@ -3181,7 +3181,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.3.4;
MARKETING_VERSION = 3.3.5;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
PRODUCT_NAME = SDL3;
@@ -3211,8 +3211,8 @@
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
DYLIB_COMPATIBILITY_VERSION = 305.0.0;
DYLIB_CURRENT_VERSION = 305.0.0;
DYLIB_COMPATIBILITY_VERSION = 306.0.0;
DYLIB_CURRENT_VERSION = 306.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -3244,7 +3244,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.3.4;
MARKETING_VERSION = 3.3.5;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
+1 -1
View File
@@ -1,4 +1,4 @@
Title SDL 3.3.4
Title SDL 3.3.5
Version 1
Description SDL Library for macOS (http://www.libsdl.org)
DefaultLocation /Library/Frameworks
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 3;
private static final int SDL_MICRO_VERSION = 4;
private static final int SDL_MICRO_VERSION = 5;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
+1 -1
View File
@@ -20,7 +20,7 @@
*/
/**
* Main include header for the SDL library, version 3.3.4
* Main include header for the SDL library, version 3.3.5
*
* It is almost always best to include just this one header instead of
* picking out individual headers included here. There are exceptions to
+9
View File
@@ -577,6 +577,15 @@ extern SDL_DECLSPEC SDL_AudioDeviceID * SDLCALL SDL_GetAudioRecordingDevices(int
/**
* Get the human-readable name of a specific audio device.
*
* **WARNING**: this function will work with SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK
* and SDL_AUDIO_DEVICE_DEFAULT_RECORDING, returning the current default
* physical devices' names. However, as the default device may change at any
* time, it is likely better to show a generic name to the user, like "System
* default audio device" or perhaps "default [currently %s]". Do not store
* this name to disk to reidentify the device in a later run of the program,
* as the default might change in general, and the string will be the name of
* a specific device and not the abstract system default.
*
* \param devid the instance ID of the device to query.
* \returns the name of the audio device, or NULL on failure; call
* SDL_GetError() for more information.
+1 -1
View File
@@ -2361,7 +2361,7 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties(
* When no such structure is provided, SDL will use Vulkan API version 1.0 and
* a minimal set of features. The requested API version influences how the
* feature_list is processed by SDL. When requesting API version 1.0, the
* feature_list is ignored. Only the vulkan_10_phyisical_device_features and
* feature_list is ignored. Only the vulkan_10_physical_device_features and
* the extension lists are used. When requesting API version 1.1, the
* feature_list is scanned for feature structures introduced in Vulkan 1.1.
* When requesting Vulkan 1.2 or higher, the feature_list is additionally
-26
View File
@@ -787,32 +787,6 @@ extern "C" {
*/
#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
/**
* Dictate that windows on Emscripten will fill the whole browser window.
*
* When enabled, the canvas element fills the entire document. Resize events
* will be generated as the browser window is resized, as that will adjust the
* canvas size as well. The canvas will cover anything else on the page,
* including any controls provided by Emscripten in its generated HTML file
* (in fact, any elements on the page that aren't the canvas will be moved
* into a hidden `div` element).
*
* Often times this is desirable for a browser-based game, but it means
* several things that we expect of an SDL window on other platforms might not
* work as expected, such as minimum window sizes and aspect ratios.
*
* This hint overrides SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN
* properties when creating an SDL window.
*
* This hint only applies to the Emscripten platform.
*
* This hint can be set at any time (before creating the window, or to toggle
* its state later). Only one window can fill the document at a time.
*
* \since This hint is available since SDL 3.4.0.
*/
#define SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT "SDL_EMSCRIPTEN_FILL_DOCUMENT"
/**
* A variable that controls whether the on-screen keyboard should be shown
* when text input is active.
+4 -4
View File
@@ -203,10 +203,10 @@ typedef Uint32 SDL_MouseButtonFlags;
* \sa SDL_SetRelativeMouseTransform
*/
typedef void (SDLCALL *SDL_MouseMotionTransformCallback)(
void *userdata,
Uint64 timestamp,
SDL_Window *window,
SDL_MouseID mouseID,
void *userdata,
Uint64 timestamp,
SDL_Window *window,
SDL_MouseID mouseID,
float *x, float *y
);
+12 -4
View File
@@ -241,9 +241,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
* left edge of the image, if this surface is being used as a cursor.
* - `SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER`: the hotspot pixel offset from the
* top edge of the image, if this surface is being used as a cursor.
* - `SDL_PROP_SURFACE_ROTATION_NUMBER`: the number of degrees a surface's
* data is meant to be rotated clockwise to make the image right-side up.
* Default 0. This is used by the camera API, if a mobile device is oriented
* - `SDL_PROP_SURFACE_ROTATION_FLOAT`: the number of degrees a surface's data
* is meant to be rotated clockwise to make the image right-side up. Default
* 0. This is used by the camera API, if a mobile device is oriented
* differently than what its camera provides (i.e. - the camera always
* provides portrait images but the phone is being held in landscape
* orientation). Since SDL 3.4.0.
@@ -263,7 +263,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac
#define SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING "SDL.surface.tonemap"
#define SDL_PROP_SURFACE_HOTSPOT_X_NUMBER "SDL.surface.hotspot.x"
#define SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER "SDL.surface.hotspot.y"
#define SDL_PROP_SURFACE_ROTATION_NUMBER "SDL.surface.rotation"
#define SDL_PROP_SURFACE_ROTATION_FLOAT "SDL.surface.rotation"
/**
* Set the colorspace used by a surface.
@@ -1027,6 +1027,14 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipM
* larger than the original, with the background filled in with the colorkey,
* if available, or RGBA 255/255/255/0 if not.
*
* If `surface` has the SDL_PROP_SURFACE_ROTATION_FLOAT property set on it,
* the new copy will have the adjusted value set: if the rotation property is
* 90 and `angle` was 30, the new surface will have a property value of 60
* (that is: to be upright vs gravity, this surface needs to rotate 60 more
* degrees). However, note that further rotations on the new surface in this
* example will produce unexpected results, since the image will have resized
* and padded to accommodate the not-90 degree angle.
*
* \param surface the surface to rotate.
* \param angle the rotation angle, in degrees.
* \returns a rotated copy of the surface or NULL on failure; call
+1 -1
View File
@@ -62,7 +62,7 @@ extern "C" {
*
* \since This macro is available since SDL 3.2.0.
*/
#define SDL_MICRO_VERSION 4
#define SDL_MICRO_VERSION 5
/**
* This macro turns the version numbers into a numeric value.
+33 -14
View File
@@ -215,6 +215,7 @@ typedef Uint64 SDL_WindowFlags;
#define SDL_WINDOW_TOOLTIP SDL_UINT64_C(0x0000000000040000) /**< window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window */
#define SDL_WINDOW_POPUP_MENU SDL_UINT64_C(0x0000000000080000) /**< window should be treated as a popup menu, requires a parent window */
#define SDL_WINDOW_KEYBOARD_GRABBED SDL_UINT64_C(0x0000000000100000) /**< window has grabbed keyboard input */
#define SDL_WINDOW_FILL_DOCUMENT SDL_UINT64_C(0x0000000000200000) /**< window is in fill-document mode (Emscripten only), since SDL 3.4.0 */
#define SDL_WINDOW_VULKAN SDL_UINT64_C(0x0000000010000000) /**< window usable for Vulkan surface */
#define SDL_WINDOW_METAL SDL_UINT64_C(0x0000000020000000) /**< window usable for Metal view */
#define SDL_WINDOW_TRANSPARENT SDL_UINT64_C(0x0000000040000000) /**< window with transparent buffer */
@@ -1370,15 +1371,6 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
*
* - `SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_CANVAS_ID_STRING`: the id given to the
* canvas element. This should start with a '#' sign
* - `SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN`: true to make
* the canvas element fill the entire document. Resize events will be
* generated as the browser window is resized, as that will adjust the
* canvas size as well. The canvas will cover anything else on the page,
* including any controls provided by Emscripten in its generated HTML file.
* Often times this is desirable for a browser-based game, but it means
* several things that we expect of an SDL window on other platforms might
* not work as expected, such as minimum window sizes and aspect ratios.
* Default false.
* - `SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING`: override the
* binding element for keyboard inputs for this canvas. The variable can be
* one of:
@@ -1453,7 +1445,6 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop
#define SDL_PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "SDL.window.create.win32.pixel_format_hwnd"
#define SDL_PROP_WINDOW_CREATE_X11_WINDOW_NUMBER "SDL.window.create.x11.window"
#define SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_CANVAS_ID_STRING "SDL.window.create.emscripten.canvas_id"
#define SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN "SDL.window.create.emscripten.fill_document"
#define SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING "SDL.window.create.emscripten.keyboard_element"
/**
@@ -1623,9 +1614,6 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window)
*
* - `SDL_PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING`: the id the canvas element
* will have
* - `SDL_PROP_WINDOW_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN`: true if the canvas is
* set to consume the entire browser window, bypassing some SDL window
* functionality.
* - `SDL_PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING`: the keyboard
* element that associates keyboard events to this window
*
@@ -1675,7 +1663,6 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window
#define SDL_PROP_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen"
#define SDL_PROP_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window"
#define SDL_PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING "SDL.window.emscripten.canvas_id"
#define SDL_PROP_WINDOW_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN "SDL.window.emscripten.fill_document"
#define SDL_PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING "SDL.window.emscripten.keyboard_element"
/**
@@ -1694,6 +1681,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window
* \sa SDL_MinimizeWindow
* \sa SDL_SetWindowFullscreen
* \sa SDL_SetWindowMouseGrab
* \sa SDL_SetWindowFillDocument
* \sa SDL_ShowWindow
*/
extern SDL_DECLSPEC SDL_WindowFlags SDLCALL SDL_GetWindowFlags(SDL_Window *window);
@@ -2163,6 +2151,37 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowResizable(SDL_Window *window, bool
*/
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window *window, bool on_top);
/**
* Set the window to fill the current document space (Emscripten only).
*
* This will add or remove the window's `SDL_WINDOW_FILL_DOCUMENT` flag.
*
* Currently this flag only applies to the Emscripten target.
*
* When enabled, the canvas element fills the entire document. Resize events
* will be generated as the browser window is resized, as that will adjust the
* canvas size as well. The canvas will cover anything else on the page,
* including any controls provided by Emscripten in its generated HTML file
* (in fact, any elements on the page that aren't the canvas will be moved
* into a hidden `div` element).
*
* Often times this is desirable for a browser-based game, but it means
* several things that we expect of an SDL window on other platforms might not
* work as expected, such as minimum window sizes and aspect ratios.
*
* \param window the window of which to change the fill-document state.
* \param fill true to set the window to fill the document, false to disable.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function should only be called on the main thread.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_GetWindowFlags
*/
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowFillDocument(SDL_Window *window, bool fill);
/**
* Show a window.
*
+8
View File
@@ -1579,6 +1579,14 @@ const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
// remains valid (in case the device is unplugged at the wrong moment), we hold the
// subsystem_rwlock while we copy the string.
SDL_LockRWLockForReading(current_audio.subsystem_rwlock);
// Allow default device IDs to be used, just return the current default physical device's name.
if (devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) {
devid = current_audio.default_playback_device_id;
} else if (devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING) {
devid = current_audio.default_recording_device_id;
}
SDL_FindInHashTable(islogical ? current_audio.device_hash_logical : current_audio.device_hash_physical, (const void *) (uintptr_t) devid, &vdev);
if (!vdev) {
SDL_SetError("Invalid audio device instance ID");
+3 -3
View File
@@ -150,7 +150,7 @@ static size_t GetFrameBufLen(const SDL_CameraSpec *spec)
return wxh * SDL_BYTESPERPIXEL(fmt);
}
static SDL_CameraFrameResult ZombieAcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult ZombieAcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
const SDL_CameraSpec *spec = &device->actual_spec;
@@ -832,7 +832,7 @@ bool SDL_CameraThreadIterate(SDL_Camera *device)
SDL_Surface *output_surface = NULL;
SurfaceList *slist = NULL;
Uint64 timestampNS = 0;
int rotation = 0;
float rotation = 0.0f;
// AcquireFrame SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitDevice instead!
const SDL_CameraFrameResult rc = device->AcquireFrame(device, device->acquire_surface, &timestampNS, &rotation);
@@ -929,7 +929,7 @@ bool SDL_CameraThreadIterate(SDL_Camera *device)
acquired->pixels = NULL;
acquired->pitch = 0;
SDL_SetNumberProperty(SDL_GetSurfaceProperties(output_surface), SDL_PROP_SURFACE_ROTATION_NUMBER, rotation);
SDL_SetFloatProperty(SDL_GetSurfaceProperties(output_surface), SDL_PROP_SURFACE_ROTATION_FLOAT, rotation);
// make the filled output surface available to the app.
SDL_LockMutex(device->lock);
+2 -2
View File
@@ -99,7 +99,7 @@ struct SDL_Camera
// These are, initially, set from camera_driver, but we might swap them out with Zombie versions on disconnect/failure.
bool (*WaitDevice)(SDL_Camera *device);
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation);
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation);
void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame);
// All supported formats/dimensions for this device.
@@ -178,7 +178,7 @@ typedef struct SDL_CameraDriverImpl
bool (*OpenDevice)(SDL_Camera *device, const SDL_CameraSpec *spec);
void (*CloseDevice)(SDL_Camera *device);
bool (*WaitDevice)(SDL_Camera *device);
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation); // set frame->pixels, frame->pitch, *timestampNS, and *rotation!
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation); // set frame->pixels, frame->pitch, *timestampNS, and *rotation!
void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame); // Reclaim frame->pixels and frame->pitch!
void (*FreeDeviceHandle)(SDL_Camera *device); // SDL is done with this device; free the handle from SDL_AddCamera()
void (*Deinitialize)(void);
+2 -2
View File
@@ -296,7 +296,7 @@ static bool ANDROIDCAMERA_WaitDevice(SDL_Camera *device)
return true; // this isn't used atm, since we run our own thread via onImageAvailable callbacks.
}
static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY;
media_status_t res;
@@ -380,7 +380,7 @@ static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_
dev_rotation = -dev_rotation; // we want to subtract this value, instead of add, if back-facing.
}
*rotation = dev_rotation + device->hidden->rotation; // current phone orientation, static camera orientation in relation to phone.
*rotation = (float) (dev_rotation + device->hidden->rotation); // current phone orientation, static camera orientation in relation to phone.
return result;
}
+61 -9
View File
@@ -157,7 +157,7 @@ static bool COREMEDIA_WaitDevice(SDL_Camera *device)
return true; // this isn't used atm, since we run our own thread out of Grand Central Dispatch.
}
static SDL_CameraFrameResult COREMEDIA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult COREMEDIA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY;
SDLPrivateCameraData *hidden = (__bridge SDLPrivateCameraData *) device->hidden;
@@ -243,21 +243,21 @@ static SDL_CameraFrameResult COREMEDIA_AcquireFrame(SDL_Camera *device, SDL_Surf
// there is probably math for this, but this is easy to slap into a table.
// rotation = rotations[uiorientation-1][devorientation-1];
if (device->position == SDL_CAMERA_POSITION_BACK_FACING) {
static const int back_rotations[4][4] = {
static const Uint16 back_rotations[4][4] = {
{ 90, 90, 90, 90 }, // ui portrait
{ 270, 270, 270, 270 }, // ui portait upside down
{ 0, 0, 0, 0 }, // ui landscape left
{ 180, 180, 180, 180 } // ui landscape right
};
*rotation = back_rotations[ui_orientation - 1][device_orientation - 1];
*rotation = (float) back_rotations[ui_orientation - 1][device_orientation - 1];
} else {
static const int front_rotations[4][4] = {
static const Uint16 front_rotations[4][4] = {
{ 90, 90, 270, 270 }, // ui portrait
{ 270, 270, 90, 90 }, // ui portait upside down
{ 0, 0, 180, 180 }, // ui landscape left
{ 180, 180, 0, 0 } // ui landscape right
};
*rotation = front_rotations[ui_orientation - 1][device_orientation - 1];
*rotation = (float) front_rotations[ui_orientation - 1][device_orientation - 1];
}
#endif
@@ -320,10 +320,37 @@ static bool COREMEDIA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec)
const float FRAMERATE_EPSILON = 0.01f;
for (AVFrameRateRange *framerate in format.videoSupportedFrameRateRanges) {
if (rate > (framerate.minFrameRate - FRAMERATE_EPSILON) &&
rate < (framerate.maxFrameRate + FRAMERATE_EPSILON)) {
spec_format = format;
break;
// Check if the requested rate is within the supported range
if (rate >= (framerate.minFrameRate - FRAMERATE_EPSILON) &&
rate <= (framerate.maxFrameRate + FRAMERATE_EPSILON)) {
// Prefer formats with narrower frame rate ranges that are closer to our target
// This helps avoid formats that support a wide range (like 10-60 FPS)
// when we want a specific rate (like 30 FPS)
bool should_select = false;
if (spec_format == nil) {
should_select = true;
} else {
AVFrameRateRange *current_range = spec_format.videoSupportedFrameRateRanges.firstObject;
float current_range_width = current_range.maxFrameRate - current_range.minFrameRate;
float new_range_width = framerate.maxFrameRate - framerate.minFrameRate;
// Prefer formats with narrower ranges, or if ranges are similar, prefer closer to target
if (new_range_width < current_range_width) {
should_select = true;
} else if (SDL_fabsf(new_range_width - current_range_width) < 0.1f) {
// Similar range width, prefer the one closer to our target rate
float current_distance = SDL_fabsf(rate - current_range.minFrameRate);
float new_distance = SDL_fabsf(rate - framerate.minFrameRate);
if (new_distance < current_distance) {
should_select = true;
}
}
}
if (should_select) {
spec_format = format;
}
}
}
@@ -339,6 +366,22 @@ static bool COREMEDIA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec)
}
avdevice.activeFormat = spec_format;
// Try to set the frame duration to enforce the requested frame rate
const float frameRate = (float)spec->framerate_numerator / spec->framerate_denominator;
const CMTime frameDuration = CMTimeMake(1, (int32_t)frameRate);
// Check if the device supports setting frame duration
if ([avdevice respondsToSelector:@selector(setActiveVideoMinFrameDuration:)] &&
[avdevice respondsToSelector:@selector(setActiveVideoMaxFrameDuration:)]) {
@try {
avdevice.activeVideoMinFrameDuration = frameDuration;
avdevice.activeVideoMaxFrameDuration = frameDuration;
} @catch (NSException *exception) {
// Some devices don't support setting frame duration, that's okay
}
}
[avdevice unlockForConfiguration];
AVCaptureSession *session = [[AVCaptureSession alloc] init];
@@ -394,6 +437,15 @@ static bool COREMEDIA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec)
}
[session addOutput:output];
// Try to set the frame rate on the connection
AVCaptureConnection *connection = [output connectionWithMediaType:AVMediaTypeVideo];
if (connection && connection.isVideoMinFrameDurationSupported) {
connection.videoMinFrameDuration = frameDuration;
if (connection.isVideoMaxFrameDurationSupported) {
connection.videoMaxFrameDuration = frameDuration;
}
}
[session commitConfiguration];
SDLPrivateCameraData *hidden = [[SDLPrivateCameraData alloc] init];
+1 -1
View File
@@ -38,7 +38,7 @@ static bool DUMMYCAMERA_WaitDevice(SDL_Camera *device)
return SDL_Unsupported();
}
static SDL_CameraFrameResult DUMMYCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult DUMMYCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
SDL_Unsupported();
return SDL_CAMERA_FRAME_ERROR;
@@ -39,7 +39,7 @@ static bool EMSCRIPTENCAMERA_WaitDevice(SDL_Camera *device)
return false;
}
static SDL_CameraFrameResult EMSCRIPTENCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult EMSCRIPTENCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
void *rgba = SDL_malloc(device->actual_spec.width * device->actual_spec.height * 4);
if (!rgba) {
@@ -430,7 +430,7 @@ static void SDLCALL CleanupIMFMediaBuffer(void *userdata, void *value)
SDL_free(objs);
}
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
SDL_assert(device->hidden->current_sample != NULL);
@@ -562,7 +562,7 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_CopyFrame(SDL_Surface *frame, const
return SDL_CAMERA_FRAME_READY;
}
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
SDL_assert(device->hidden->current_sample != NULL);
+1 -1
View File
@@ -577,7 +577,7 @@ static bool PIPEWIRECAMERA_WaitDevice(SDL_Camera *device)
return true;
}
static SDL_CameraFrameResult PIPEWIRECAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult PIPEWIRECAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
struct pw_buffer *b;
+2 -2
View File
@@ -125,7 +125,7 @@ static bool V4L2_WaitDevice(SDL_Camera *device)
return false;
}
static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
const int fd = device->hidden->fd;
const io_method io = device->hidden->io;
@@ -801,7 +801,7 @@ static void MaybeAddDevice(const char *path)
const int stepw = (int) frmsizeenum.stepwise.step_width;
const int steph = (int) frmsizeenum.stepwise.step_height;
for (int w = minw; w <= maxw; w += stepw) {
for (int h = minh; w <= maxh; w += steph) {
for (int h = minh; h <= maxh; h += steph) {
#if DEBUG_CAMERA
SDL_Log("CAMERA: * Has %s size %dx%d", (frmsizeenum.type == V4L2_FRMSIZE_TYPE_STEPWISE) ? "stepwise" : "continuous", w, h);
#endif
+1 -1
View File
@@ -190,7 +190,7 @@ static bool VITACAMERA_WaitDevice(SDL_Camera *device)
return true;
}
static SDL_CameraFrameResult VITACAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
static SDL_CameraFrameResult VITACAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, float *rotation)
{
SceCameraRead read = {0};
read.size = sizeof(SceCameraRead);
+4 -4
View File
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,3,4,0
PRODUCTVERSION 3,3,4,0
FILEVERSION 3,3,5,0
PRODUCTVERSION 3,3,5,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "3, 3, 4, 0\0"
VALUE "FileVersion", "3, 3, 5, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL3.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "3, 3, 4, 0\0"
VALUE "ProductVersion", "3, 3, 5, 0\0"
END
END
BLOCK "VarFileInfo"
+1
View File
@@ -1270,6 +1270,7 @@ SDL3_0.0.0 {
SDL_RotateSurface;
SDL_LoadSurface_IO;
SDL_LoadSurface;
SDL_SetWindowFillDocument;
# extra symbols go here (don't modify this line)
local: *;
};
+1
View File
@@ -1296,3 +1296,4 @@
#define SDL_RotateSurface SDL_RotateSurface_REAL
#define SDL_LoadSurface_IO SDL_LoadSurface_IO_REAL
#define SDL_LoadSurface SDL_LoadSurface_REAL
#define SDL_SetWindowFillDocument SDL_SetWindowFillDocument_REAL
+1
View File
@@ -1304,3 +1304,4 @@ SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateAnimatedCursor,(SDL_CursorFrameInfo *a,int
SDL_DYNAPI_PROC(SDL_Surface*,SDL_RotateSurface,(SDL_Surface *a,float b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface_IO,(SDL_IOStream *a,bool b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface,(const char *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_SetWindowFillDocument,(SDL_Window *a,bool b),(a,b),return)
+1 -9
View File
@@ -1238,16 +1238,8 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
SDL_AddWindowEventWatch(SDL_WINDOW_EVENT_WATCH_NORMAL, SDL_RendererEventWatch, renderer);
}
#ifdef SDL_PLATFORM_EMSCRIPTEN // don't change vsync on Emscripten unless explicitly requested; we already set this with a mainloop, and a 0 default causes problems here.
if (SDL_HasProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER)) {
const int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
SDL_SetRenderVSync(renderer, vsync);
}
#else // everything else defaults to no vsync if not requested.
const int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
SDL_SetRenderVSync(renderer, vsync);
#endif
SDL_CalculateSimulatedVSyncInterval(renderer, window);
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
+4 -4
View File
@@ -1787,10 +1787,10 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
}
}
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32); // SDL_PIXELFORMAT_ARGB8888 on little endian systems
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX32);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX32);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR2101010);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA64_FLOAT);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
+1 -1
View File
@@ -1933,7 +1933,7 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
// RGBA32 is always supported with OpenGL
if (bgra_supported) {
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32); // SDL_PIXELFORMAT_ARGB8888 on little endian systems
}
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
+4 -4
View File
@@ -2430,10 +2430,10 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
data->window_framebuffer = (GLuint)window_framebuffer;
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32); // SDL_PIXELFORMAT_ARGB8888 on little endian systems
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX32);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX32);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
#ifdef SDL_HAVE_YUV
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
+25 -9
View File
@@ -395,9 +395,11 @@ static bool VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImag
static SDL_PixelFormat VULKAN_VkFormatToSDLPixelFormat(VkFormat vkFormat)
{
switch (vkFormat) {
case VK_FORMAT_B8G8R8A8_UNORM:
return SDL_PIXELFORMAT_ARGB8888;
case VK_FORMAT_R8G8B8A8_UNORM:
return SDL_PIXELFORMAT_RGBA32;
case VK_FORMAT_B8G8R8A8_UNORM:
return SDL_PIXELFORMAT_BGRA32;
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
return SDL_PIXELFORMAT_ABGR8888;
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
return SDL_PIXELFORMAT_ABGR2101010;
@@ -430,8 +432,12 @@ static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat, int plane)
return 2;
case VK_FORMAT_R16G16_UNORM:
return 4;
case VK_FORMAT_R8G8B8A8_SRGB:
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SRGB:
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
return 4;
case VK_FORMAT_R16G16B16A16_SFLOAT:
@@ -454,16 +460,23 @@ static VkFormat SDLPixelFormatToVkTextureFormat(Uint32 format, Uint32 output_col
return VK_FORMAT_R16G16B16A16_SFLOAT;
case SDL_PIXELFORMAT_ABGR2101010:
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
case SDL_PIXELFORMAT_ARGB8888:
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return VK_FORMAT_B8G8R8A8_SRGB;
}
return VK_FORMAT_B8G8R8A8_UNORM;
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_RGBA32:
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return VK_FORMAT_R8G8B8A8_SRGB;
}
return VK_FORMAT_R8G8B8A8_UNORM;
case SDL_PIXELFORMAT_BGRA32:
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return VK_FORMAT_B8G8R8A8_SRGB;
}
return VK_FORMAT_B8G8R8A8_UNORM;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
case SDL_PIXELFORMAT_ABGR8888:
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return VK_FORMAT_A8B8G8R8_SRGB_PACK32;
}
return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
#endif
case SDL_PIXELFORMAT_INDEX8:
return VK_FORMAT_R8_UNORM;
case SDL_PIXELFORMAT_YUY2:
@@ -4553,8 +4566,11 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
VULKAN_InvalidateCachedState(renderer);
renderer->name = VULKAN_RenderDriver.name;
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32); // SDL_PIXELFORMAT_ARGB8888 on little endian systems
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
#endif
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR2101010);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA64_FLOAT);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
+5 -4
View File
@@ -137,13 +137,14 @@ static bool STEAM_EnumerateStorageDirectory(void *userdata, const char *path, SD
}
fname = file + dirlen;
} else {
// Make sure this is a top-level file
if (SDL_strchr(file, '/') != NULL) {
continue;
}
fname = file;
}
// Make sure this is a file in the current directory
if (SDL_strchr(fname, '/') != NULL) {
continue;
}
switch (callback(callback_userdata, dirname, fname)) {
case SDL_ENUM_SUCCESS:
done = true;
+9
View File
@@ -2497,6 +2497,15 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const
}
}
break;
case SDLK_D:
if (withControl) {
/* Ctrl-D toggle fill-document */
SDL_Window *window = SDL_GetWindowFromEvent(event);
if (window) {
SDL_SetWindowFillDocument(window, !((SDL_GetWindowFlags(window) & SDL_WINDOW_FILL_DOCUMENT) != 0));
}
}
break;
case SDLK_P:
if (withAlt) {
/* Alt-P cycle through progress states */
+2 -2
View File
@@ -1107,8 +1107,8 @@ SDL_GLContext SDL_EGL_CreateContext(SDL_VideoDevice *_this, EGLSurface egl_surfa
return NULL;
}
// The default swap interval is 1, according to the spec
_this->egl_data->egl_swapinterval = 1;
// The default swap interval is 1, according to the spec, but SDL3's policy is to default vsync to off by default.
_this->egl_data->egl_swapinterval = 0;
if (!SDL_EGL_MakeCurrent(_this, egl_surface, (SDL_GLContext)egl_context)) {
// Delete the context
+8
View File
@@ -2198,6 +2198,14 @@ SDL_Surface *SDL_RotateSurface(SDL_Surface *surface, float angle)
SDL_DestroySurface(convert);
}
}
if (rotated) {
if (SDL_HasProperty(surface->props, SDL_PROP_SURFACE_ROTATION_FLOAT)) {
const float rotation = (SDL_GetNumberProperty(surface->props, SDL_PROP_SURFACE_ROTATION_FLOAT, 0) - angle);
SDL_SetFloatProperty(SDL_GetSurfaceProperties(rotated), SDL_PROP_SURFACE_ROTATION_FLOAT, rotation);
}
}
return rotated;
}
+1
View File
@@ -312,6 +312,7 @@ struct SDL_VideoDevice
bool (*FlashWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
bool (*ApplyWindowProgress)(SDL_VideoDevice *_this, SDL_Window *window);
bool (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, bool focusable);
bool (*SetWindowFillDocument)(SDL_VideoDevice *_this, SDL_Window *window, bool fill);
bool (*SyncWindow)(SDL_VideoDevice *_this, SDL_Window *window);
bool (*ReconfigureWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_WindowFlags flags);
+24 -1
View File
@@ -2199,7 +2199,7 @@ SDL_PixelFormat SDL_GetWindowPixelFormat(SDL_Window *window)
}
#define CREATE_FLAGS \
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_TRANSPARENT | SDL_WINDOW_NOT_FOCUSABLE)
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_TRANSPARENT | SDL_WINDOW_NOT_FOCUSABLE | SDL_WINDOW_FILL_DOCUMENT)
static SDL_INLINE bool IsAcceptingDragAndDrop(void)
{
@@ -2557,6 +2557,10 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props)
window->external_graphics_context = external_graphics_context;
window->constrain_popup = SDL_GetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN, true);
if (!_this->SetWindowFillDocument) {
window->flags &= ~SDL_WINDOW_FILL_DOCUMENT; // not an error, just unsupported here, so remove the flag.
}
if (_this->windows) {
_this->windows->prev = window;
}
@@ -3914,6 +3918,25 @@ bool SDL_SetWindowFocusable(SDL_Window *window, bool focusable)
return true;
}
bool SDL_SetWindowFillDocument(SDL_Window *window, bool fill)
{
CHECK_WINDOW_MAGIC(window, false);
const bool want = (fill != false); // normalize the flag.
const bool have = ((window->flags & SDL_WINDOW_FILL_DOCUMENT) != 0);
if ((want != have) && (_this->SetWindowFillDocument)) {
if (!_this->SetWindowFillDocument(_this, window, want)) {
return false;
} else if (want) {
window->flags |= SDL_WINDOW_FILL_DOCUMENT;
} else {
window->flags &= ~SDL_WINDOW_FILL_DOCUMENT;
}
}
return true;
}
void SDL_UpdateWindowGrab(SDL_Window *window)
{
bool keyboard_grabbed, mouse_grabbed;
+21 -35
View File
@@ -50,6 +50,7 @@ static SDL_FullscreenResult Emscripten_SetWindowFullscreen(SDL_VideoDevice *_thi
static void Emscripten_PumpEvents(SDL_VideoDevice *_this);
static void Emscripten_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
static bool Emscripten_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
static bool Emscripten_SetWindowFillDocument(SDL_VideoDevice *_this, SDL_Window *window, bool fill);
SDL_Window *Emscripten_fill_document_window = NULL;
@@ -58,11 +59,8 @@ static int pending_swap_interval = -1;
// Emscripten driver bootstrap functions
static void SDLCALL Emscripten_FillDocHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint);
static void Emscripten_DeleteDevice(SDL_VideoDevice *device)
{
SDL_RemoveHintCallback(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT, Emscripten_FillDocHintChanged, device);
SDL_free(device);
}
@@ -177,6 +175,7 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void)
device->GetWindowSizeInPixels = Emscripten_GetWindowSizeInPixels;
device->DestroyWindow = Emscripten_DestroyWindow;
device->SetWindowFullscreen = Emscripten_SetWindowFullscreen;
device->SetWindowFillDocument = Emscripten_SetWindowFillDocument;
device->CreateWindowFramebuffer = Emscripten_CreateWindowFramebuffer;
device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
@@ -197,8 +196,6 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void)
Emscripten_ListenSystemTheme();
device->system_theme = Emscripten_GetSystemTheme();
SDL_AddHintCallback(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT, Emscripten_FillDocHintChanged, device);
return device;
}
@@ -463,14 +460,16 @@ EMSCRIPTEN_KEEPALIVE void requestFullscreenThroughSDL(SDL_Window *window)
SDL_SetWindowFullscreen(window, true);
}
static void Emscripten_SetWindowFillDocState(SDL_Window *window, bool enable)
static bool Emscripten_SetWindowFillDocument(SDL_VideoDevice *_this, SDL_Window *window, bool fill)
{
SDL_WindowData *wdata = window->internal;
SDL_assert(!Emscripten_fill_document_window || !enable); // one at a time, sorry.
if (fill && Emscripten_fill_document_window && (Emscripten_fill_document_window != window)) {
return SDL_SetError("Only one fill-document window allowed at a time.");
}
// fill_document takes up the entire page and resizes as the browser window resizes.
if (enable) {
if (fill) {
Emscripten_fill_document_window = window;
const int w = MAIN_THREAD_EM_ASM_INT({ return window.innerWidth; });
@@ -558,20 +557,8 @@ static void Emscripten_SetWindowFillDocState(SDL_Window *window, bool enable)
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, wdata->non_fill_document_width, wdata->non_fill_document_height);
}
}
}
static void SDLCALL Emscripten_FillDocHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
const bool enabled = SDL_GetStringBoolean(hint, false);
if (Emscripten_fill_document_window && !enabled) {
Emscripten_SetWindowFillDocState(Emscripten_fill_document_window, false);
} else if (!Emscripten_fill_document_window && enabled) {
/// there's currently only ever one canvas, but if this changes later, we can choose the one with keyboard focus or something.
SDL_VideoDevice *device = (SDL_VideoDevice *) userdata;
if (device && device->windows) { // take first window in the list for now.
Emscripten_SetWindowFillDocState(device->windows, true);
}
}
return true;
}
static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props)
@@ -580,6 +567,12 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
double css_w, css_h;
const char *selector;
bool fill_document = ((window->flags & SDL_WINDOW_FILL_DOCUMENT) != 0);
if (fill_document && Emscripten_fill_document_window) {
fill_document = false; // only one allowed at a time.
window->flags &= ~SDL_WINDOW_FILL_DOCUMENT; // !!! FIXME: should this fail instead?
}
// Allocate window internal data
wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData));
if (!wdata) {
@@ -598,15 +591,6 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
}
wdata->keyboard_element = SDL_strdup(selector);
bool fill_document;
if (Emscripten_fill_document_window) {
fill_document = false; // only one allowed at a time.
} else if (SDL_GetHint(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT)) {
fill_document = SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT, false);
} else {
fill_document = SDL_GetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN, false);
}
if (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) {
wdata->pixel_ratio = emscripten_get_device_pixel_ratio();
} else {
@@ -629,7 +613,7 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
wdata->non_fill_document_width = window->w;
wdata->non_fill_document_height = window->h;
Emscripten_SetWindowFillDocState(window, fill_document);
Emscripten_SetWindowFillDocument(_this, window, fill_document);
// One window, it always has focus
SDL_SetMouseFocus(window);
@@ -647,7 +631,6 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
// Ensure various things are added to the window's properties
SDL_SetStringProperty(window->props, SDL_PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING, wdata->canvas_id);
SDL_SetStringProperty(window->props, SDL_PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING, wdata->keyboard_element);
SDL_SetBooleanProperty(window->props, SDL_PROP_WINDOW_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN, fill_document);
// Window has been successfully created
return true;
@@ -695,9 +678,7 @@ static void Emscripten_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *data;
if (Emscripten_fill_document_window == window) {
Emscripten_SetWindowFillDocState(window, false);
}
Emscripten_SetWindowFillDocument(_this, window, false);
if (window->internal) {
data = window->internal;
@@ -812,6 +793,11 @@ static bool Emscripten_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window,
// Pass PNG data to JavaScript
MAIN_THREAD_EM_ASM({
var pngData = HEAPU8.subarray($0, $0 + $1);
if (pngData.buffer instanceof SharedArrayBuffer) {
// explicitly create a copy
pngData = new Uint8Array(pngData);
}
var blob = new Blob([pngData], {type: 'image/png'});
var url = URL.createObjectURL(blob);
+3 -6
View File
@@ -1011,13 +1011,10 @@ static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int
return result;
}
SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window)
SDL_WindowData *X11_FindWindow(SDL_VideoData *videodata, Window window)
{
const SDL_VideoData *videodata = _this->internal;
int i;
if (videodata && videodata->windowlist) {
for (i = 0; i < videodata->numwindows; ++i) {
for (int i = 0; i < videodata->numwindows; ++i) {
if ((videodata->windowlist[i] != NULL) &&
(videodata->windowlist[i]->xwindow == window)) {
return videodata->windowlist[i];
@@ -1341,7 +1338,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
// xsettings internally filters events for the windows it watches
X11_HandleXsettingsEvent(_this, xevent);
data = X11_FindWindow(_this, xevent->xany.window);
data = X11_FindWindow(videodata, xevent->xany.window);
if (!data) {
// The window for KeymapNotify, etc events is 0
+1 -1
View File
@@ -33,7 +33,7 @@ extern Uint64 X11_GetEventTimestamp(unsigned long time);
extern void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_KeyboardID keyboardID, XEvent *xevent);
extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, float x, float y, unsigned long time);
extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, unsigned long time);
extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window);
extern SDL_WindowData *X11_FindWindow(SDL_VideoData *videodata, Window window);
extern bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, bool force_new_result);
extern bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y);
extern bool X11_IsWheelEvent(int button, int *xticks, int *yticks);
+6 -19
View File
@@ -130,27 +130,14 @@ static bool xinput2_version_atleast(const int version, const int wantmajor, cons
return version >= ((wantmajor * 1000) + wantminor);
}
// !!! FIXME: isn't this just X11_FindWindow?
static SDL_WindowData *xinput2_get_sdlwindowdata(SDL_VideoData *videodata, Window window)
{
int i;
for (i = 0; i < videodata->numwindows; i++) {
SDL_WindowData *d = videodata->windowlist[i];
if (d->xwindow == window) {
return d;
}
}
return NULL;
}
static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window)
{
const SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, window);
const SDL_WindowData *windowdata = X11_FindWindow(videodata, window);
return windowdata ? windowdata->window : NULL;
}
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
static void xinput2_reset_scrollable_valuators(SDL_VideoData *videodata)
static void xinput2_reset_scrollable_valuators()
{
for (int i = 0; i < scrollable_device_count; ++i) {
for (int j = 0; j < scrollable_devices[i].scroll_info_count; ++j) {
@@ -519,7 +506,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
// Handle pen proximity enter/leave
if (proev->what == XIPropertyModified && proev->property == videodata->atoms.pen_atom_wacom_serial_ids) {
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event);
SDL_WindowData *windowdata = X11_FindWindow(videodata, xev->event);
X11_NotifyPenProximityChange(_this, windowdata ? windowdata->window : NULL, proev->deviceid);
}
} break;
@@ -546,7 +533,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
case XI_KeyRelease:
{
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event);
SDL_WindowData *windowdata = X11_FindWindow(videodata, xev->event);
XEvent xevent;
if (xev->deviceid != xev->sourceid) {
@@ -615,7 +602,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
}
} else if (!pointer_emulated) {
// Otherwise assume a regular mouse
SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, xev->event);
SDL_WindowData *windowdata = X11_FindWindow(videodata, xev->event);
int x_ticks = 0, y_ticks = 0;
// Slave pointer devices don't have button remapping applied automatically, so do it manually.
@@ -643,7 +630,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
case XI_Enter:
xinput2_reset_scrollable_valuators(videodata);
xinput2_reset_scrollable_valuators();
break;
#endif
+19 -4
View File
@@ -102,6 +102,21 @@ define_property(TARGET PROPERTY SDL_NONINTERACTIVE BRIEF_DOCS "If true, target i
define_property(TARGET PROPERTY SDL_NONINTERACTIVE_ARGUMENTS BRIEF_DOCS "Argument(s) to run executable in non-interactive mode." FULL_DOCS "Argument(s) to run executable in non-interactive mode.")
define_property(TARGET PROPERTY SDL_NONINTERACTIVE_TIMEOUT BRIEF_DOCS "Timeout for noninteractive executable." FULL_DOCS "Timeout for noninteractive executable.")
if(HAVE_X11)
find_package(X11 QUIET)
if(NOT TARGET X11::X11)
set(HAVE_X11 OFF)
endif()
endif()
if(HAVE_WAYLAND)
find_package(PkgConfig QUIET)
pkg_check_modules(PkgWaylandClient QUIET IMPORTED_TARGET wayland-client)
if(NOT TARGET PkgConfig::PkgWaylandClient)
set(HAVE_WAYLAND OFF)
endif()
endif()
function(add_sdl_test_executable TARGET)
cmake_parse_arguments(AST "BUILD_DEPENDENT;NONINTERACTIVE;NEEDS_RESOURCES;TESTUTILS;THREADS;MAIN_CALLBACKS;NOTRACKMEM" "" "DEPENDS;DISABLE_THREADS_ARGS;NONINTERACTIVE_TIMEOUT;NONINTERACTIVE_ARGS;INSTALLED_ARGS;SOURCES" ${ARGN})
if(AST_UNPARSED_ARGUMENTS)
@@ -338,15 +353,15 @@ elseif(HAVE_X11 OR HAVE_WAYLAND)
add_sdl_test_executable(testnative BUILD_DEPENDENT NEEDS_RESOURCES TESTUTILS SOURCES testnative.c)
if(HAVE_X11)
target_sources(testnative PRIVATE testnativex11.c)
target_link_libraries(testnative PRIVATE X11)
target_link_libraries(testnative PRIVATE X11::X11)
endif()
if(HAVE_WAYLAND)
set_property(SOURCE ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c PROPERTY GENERATED 1)
target_sources(testnative PRIVATE testnativewayland.c ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c)
target_sources(testnative PRIVATE testnativewayland.c "${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c")
# Needed to silence the documentation warning in the generated header file
target_compile_options(testnative PRIVATE -Wno-documentation-unknown-command)
target_link_libraries(testnative PRIVATE wayland-client)
target_link_libraries(testnative PRIVATE PkgConfig::PkgWaylandClient)
endif ()
endif()
@@ -452,7 +467,7 @@ if (HAVE_WAYLAND)
add_sdl_test_executable(testwaylandcustom NEEDS_RESOURCES SOURCES testwaylandcustom.c ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c)
# Needed to silence the documentation warning in the generated header file
target_compile_options(testwaylandcustom PRIVATE -Wno-documentation-unknown-command)
target_link_libraries(testwaylandcustom PRIVATE wayland-client)
target_link_libraries(testwaylandcustom PRIVATE PkgConfig::PkgWaylandClient)
endif()
check_c_compiler_flag(-Wformat-overflow HAVE_WFORMAT_OVERFLOW)
+1
View File
@@ -109,6 +109,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
}
SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver());
SDL_Log("Current audio device name: %s", SDL_GetAudioDeviceName(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK));
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &wave.spec, NULL, NULL);
if (!stream) {
+16 -6
View File
@@ -15,6 +15,16 @@
#include <SDL3/SDL_test.h>
#include "testautomation_suites.h"
static bool test_double_isfinite(double d)
{
union {
Uint64 u64;
double d;
} d_u;
d_u.d = d;
return (d_u.u64 & 0x7ff0000000000000ULL) != 0x7ff0000000000000ULL;
}
/* ================= Test Case Implementation ================== */
/* Fixture */
@@ -1147,11 +1157,11 @@ static int SDLCALL audio_resampleLoss(void *arg)
SDL_DestroyAudioStream(stream);
SDL_free(buf_out);
signal_to_noise = 10 * SDL_log10(sum_squared_value / sum_squared_error); /* decibel */
SDLTest_AssertCheck(ISFINITE(sum_squared_value), "Sum of squared target should be finite.");
SDLTest_AssertCheck(ISFINITE(sum_squared_error), "Sum of squared error should be finite.");
SDLTest_AssertCheck(test_double_isfinite(sum_squared_value), "Sum of squared target should be finite.");
SDLTest_AssertCheck(test_double_isfinite(sum_squared_error), "Sum of squared error should be finite.");
/* Infinity is theoretically possible when there is very little to no noise */
SDLTest_AssertCheck(!ISNAN(signal_to_noise), "Signal-to-noise ratio should not be NaN.");
SDLTest_AssertCheck(ISFINITE(max_error), "Maximum conversion error should be finite.");
SDLTest_AssertCheck(test_double_isfinite(max_error), "Maximum conversion error should be finite.");
SDLTest_AssertCheck(signal_to_noise >= spec->signal_to_noise, "Conversion signal-to-noise ratio %f dB should be no less than %f dB.",
signal_to_noise, spec->signal_to_noise);
SDLTest_AssertCheck(max_error <= spec->max_error, "Maximum conversion error %f should be no more than %f.",
@@ -1440,11 +1450,11 @@ static int SDLCALL audio_formatChange(void *arg)
}
signal_to_noise = 10 * SDL_log10(sum_squared_value / sum_squared_error); /* decibel */
SDLTest_AssertCheck(ISFINITE(sum_squared_value), "Sum of squared target should be finite.");
SDLTest_AssertCheck(ISFINITE(sum_squared_error), "Sum of squared error should be finite.");
SDLTest_AssertCheck(test_double_isfinite(sum_squared_value), "Sum of squared target should be finite.");
SDLTest_AssertCheck(test_double_isfinite(sum_squared_error), "Sum of squared error should be finite.");
/* Infinity is theoretically possible when there is very little to no noise */
SDLTest_AssertCheck(!ISNAN(signal_to_noise), "Signal-to-noise ratio should not be NaN.");
SDLTest_AssertCheck(ISFINITE(max_error), "Maximum conversion error should be finite.");
SDLTest_AssertCheck(test_double_isfinite(max_error), "Maximum conversion error should be finite.");
SDLTest_AssertCheck(signal_to_noise >= target_signal_to_noise, "Conversion signal-to-noise ratio %f dB should be no less than %f dB.",
signal_to_noise, target_signal_to_noise);
SDLTest_AssertCheck(max_error <= target_max_error, "Maximum conversion error %f should be no more than %f.",
-1
View File
@@ -8,7 +8,6 @@
#include <SDL3/SDL_test.h>
#define ISFINITE(X) isfinite((float)(X))
#define ISINF(X) isinf((float)(X))
#define ISNAN(X) isnan((float)(X))
+1 -1
View File
@@ -364,7 +364,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
// device might be rotated to a different one (like an iPhone providing portrait images even if you hold
// the phone in landscape mode). The rotation is how far to rotate the image clockwise to put it right-side
// up, for how the user would expect it to be for how they are holding the device.
const int rotation = (int) SDL_GetNumberProperty(SDL_GetSurfaceProperties(frame_current), SDL_PROP_SURFACE_ROTATION_NUMBER, 0);
const float rotation = SDL_GetFloatProperty(SDL_GetSurfaceProperties(frame_current), SDL_PROP_SURFACE_ROTATION_FLOAT, 0.0f);
SDL_GetRenderOutputSize(renderer, &win_w, &win_h);
d.x = ((win_w - texture->w) / 2.0f);
d.y = ((win_h - texture->h) / 2.0f);