Compare commits
92
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ac37a8ffc | ||
|
|
7dd2915475 | ||
|
|
0ae1ddee17 | ||
|
|
db4c7e47f1 | ||
|
|
362445460e | ||
|
|
de5cb9db23 | ||
|
|
418eab29eb | ||
|
|
2f3d242183 | ||
|
|
4ad6d18203 | ||
|
|
cd4a4f8a9f | ||
|
|
a96e72da02 | ||
|
|
337f012de2 | ||
|
|
3c29b620e4 | ||
|
|
579fc161f0 | ||
|
|
22e968af4e | ||
|
|
e37e96cfff | ||
|
|
56c76c20a0 | ||
|
|
efd812c399 | ||
|
|
b2b92bbe25 | ||
|
|
a29c67ac94 | ||
|
|
f88e0aaac0 | ||
|
|
29a4a4a5d1 | ||
|
|
01000c73b0 | ||
|
|
1a5d1dfef0 | ||
|
|
2c38143834 | ||
|
|
c56a1c664c | ||
|
|
41cae64580 | ||
|
|
c6dd2662c3 | ||
|
|
f48027cf12 | ||
|
|
fabbc8d183 | ||
|
|
a142e5ef7d | ||
|
|
825c0c7691 | ||
|
|
dc30a00a26 | ||
|
|
5a05ef01ad | ||
|
|
0237997e4d | ||
|
|
4f90432a49 | ||
|
|
0cd6942bfc | ||
|
|
1beb6fdedf | ||
|
|
3b4472ecf7 | ||
|
|
faed8b620c | ||
|
|
982b778e45 | ||
|
|
3a8f1cb7c5 | ||
|
|
3c2d7ecdd6 | ||
|
|
0834f1d6ce | ||
|
|
6ce446b768 | ||
|
|
e045edb567 | ||
|
|
6cd14660cf | ||
|
|
f5ac58c9f4 | ||
|
|
c1779ca4a5 | ||
|
|
6d8309f72e | ||
|
|
cf95db46a7 | ||
|
|
b8abfeb7f3 | ||
|
|
014e24e1a8 | ||
|
|
e42071a47c | ||
|
|
1543f523b7 | ||
|
|
f2d0e965fc | ||
|
|
f782278d20 | ||
|
|
3b17d08eb2 | ||
|
|
18d367afd2 | ||
|
|
9a4faf9ab9 | ||
|
|
cb0ba020d4 | ||
|
|
f705e2f9f7 | ||
|
|
e76bffa183 | ||
|
|
a4e19dc567 | ||
|
|
4e1282617a | ||
|
|
f102ff16a2 | ||
|
|
50935a9d41 | ||
|
|
a1dde664d1 | ||
|
|
ba5325fba1 | ||
|
|
e225a10ea8 | ||
|
|
c4fba75a12 | ||
|
|
5b052e6f8c | ||
|
|
d89c3489f8 | ||
|
|
a447863e4f | ||
|
|
34db21cea8 | ||
|
|
943226edc1 | ||
|
|
281494676a | ||
|
|
413b55deb7 | ||
|
|
8222513f63 | ||
|
|
2dd20ce8e7 | ||
|
|
d308df6d62 | ||
|
|
f51b88e6b5 | ||
|
|
7cb0fa5c56 | ||
|
|
976c92a2fb | ||
|
|
15db51d7ff | ||
|
|
4aa4e6a18e | ||
|
|
0759f22a91 | ||
|
|
02036ee643 | ||
|
|
9109e05f3f | ||
|
|
2103451d00 | ||
|
|
b6db091d60 | ||
|
|
9827653c38 |
No files matched your search
+5
-5
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# See docs/release_checklist.md
|
# See docs/release_checklist.md
|
||||||
project(SDL3 LANGUAGES C VERSION "3.2.10")
|
project(SDL3 LANGUAGES C VERSION "3.2.12")
|
||||||
|
|
||||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
set(SDL3_MAINPROJECT ON)
|
set(SDL3_MAINPROJECT ON)
|
||||||
@@ -1291,8 +1291,8 @@ if(ANDROID)
|
|||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/android")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/android")
|
||||||
|
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/android/*.c")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/android/*.c")
|
||||||
sdl_sources("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
|
sdl_sources("${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
|
||||||
set_property(SOURCE "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement")
|
set_property(SOURCE "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement")
|
||||||
|
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/android/*.c")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/android/*.c")
|
||||||
set(HAVE_SDL_MISC TRUE)
|
set(HAVE_SDL_MISC TRUE)
|
||||||
@@ -3017,7 +3017,7 @@ if(SDL_GPU)
|
|||||||
set(SDL_GPU_D3D11 1)
|
set(SDL_GPU_D3D11 1)
|
||||||
set(HAVE_SDL_GPU TRUE)
|
set(HAVE_SDL_GPU TRUE)
|
||||||
endif()
|
endif()
|
||||||
if(SDL_RENDER_D3D12)
|
if(WINDOWS)
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d12/*.c")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d12/*.c")
|
||||||
set(SDL_GPU_D3D12 1)
|
set(SDL_GPU_D3D12 1)
|
||||||
set(HAVE_SDL_GPU TRUE)
|
set(HAVE_SDL_GPU TRUE)
|
||||||
@@ -3288,7 +3288,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
sdl_include_directories(PRIVATE SYSTEM "${ANDROID_NDK}/sources/android/cpufeatures")
|
sdl_include_directories(PRIVATE SYSTEM "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
|||||||
@@ -168,8 +168,8 @@
|
|||||||
</Link>
|
</Link>
|
||||||
<PreBuildEvent>
|
<PreBuildEvent>
|
||||||
<Command>
|
<Command>
|
||||||
call $(ProjectDir)..\..\src\render\direct3d12\compile_shaders_xbox.bat $(ProjectDir)..\
|
call "$(ProjectDir)..\..\src\render\direct3d12\compile_shaders_xbox.bat" "$(ProjectDir)..\"
|
||||||
call $(ProjectDir)..\..\src\gpu\d3d12\compile_shaders_xbox.bat $(ProjectDir)..\
|
call "$(ProjectDir)..\..\src\gpu\d3d12\compile_shaders_xbox.bat" "$(ProjectDir)..\"
|
||||||
</Command>
|
</Command>
|
||||||
</PreBuildEvent>
|
</PreBuildEvent>
|
||||||
<PreBuildEvent>
|
<PreBuildEvent>
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>FMWK</string>
|
<string>FMWK</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.2.10</string>
|
<string>3.2.12</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>SDLX</string>
|
<string>SDLX</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>3.2.10</string>
|
<string>3.2.12</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -3086,7 +3086,7 @@
|
|||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
DEPLOYMENT_POSTPROCESSING = YES;
|
DEPLOYMENT_POSTPROCESSING = YES;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
|
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
|
||||||
DYLIB_CURRENT_VERSION = 201.10.0;
|
DYLIB_CURRENT_VERSION = 201.12.0;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||||
@@ -3121,7 +3121,7 @@
|
|||||||
"@loader_path/Frameworks",
|
"@loader_path/Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
MARKETING_VERSION = 3.2.10;
|
MARKETING_VERSION = 3.2.12;
|
||||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||||
PRODUCT_NAME = SDL3;
|
PRODUCT_NAME = SDL3;
|
||||||
@@ -3150,7 +3150,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
|
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
|
||||||
DYLIB_CURRENT_VERSION = 201.10.0;
|
DYLIB_CURRENT_VERSION = 201.12.0;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
@@ -3182,7 +3182,7 @@
|
|||||||
"@loader_path/Frameworks",
|
"@loader_path/Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
MARKETING_VERSION = 3.2.10;
|
MARKETING_VERSION = 3.2.12;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Title SDL 3.2.10
|
Title SDL 3.2.12
|
||||||
Version 1
|
Version 1
|
||||||
Description SDL Library for macOS (http://www.libsdl.org)
|
Description SDL Library for macOS (http://www.libsdl.org)
|
||||||
DefaultLocation /Library/Frameworks
|
DefaultLocation /Library/Frameworks
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
private static final String TAG = "SDL";
|
private static final String TAG = "SDL";
|
||||||
private static final int SDL_MAJOR_VERSION = 3;
|
private static final int SDL_MAJOR_VERSION = 3;
|
||||||
private static final int SDL_MINOR_VERSION = 2;
|
private static final int SDL_MINOR_VERSION = 2;
|
||||||
private static final int SDL_MICRO_VERSION = 10;
|
private static final int SDL_MICRO_VERSION = 12;
|
||||||
/*
|
/*
|
||||||
// Display InputType.SOURCE/CLASS of events and devices
|
// Display InputType.SOURCE/CLASS of events and devices
|
||||||
//
|
//
|
||||||
|
|||||||
+30
-26
@@ -1,32 +1,6 @@
|
|||||||
|
|
||||||
SDL 3.0 has new support for high DPI displays. Interfaces provided by SDL uses the platform's native coordinates unless otherwise specified.
|
SDL 3.0 has new support for high DPI displays. Interfaces provided by SDL uses the platform's native coordinates unless otherwise specified.
|
||||||
|
|
||||||
To reconcile platform differences in their approach to high-density scaling, SDL provides the following interfaces:
|
|
||||||
- `SDL_GetWindowSize()` retrieves the window dimensions in native coordinates.
|
|
||||||
- `SDL_GetWindowSizeInPixels()` retrieves the window dimensions in pixels-addressable.
|
|
||||||
- `SDL_GetDisplayContentScale()` retrieves the suggested amplification factor when drawing in native coordinates.
|
|
||||||
- `SDL_GetWindowDisplayScale()` retrieves the suggested amplification factor when drawing in pixels-addressable.
|
|
||||||
- `SDL_GetWindowPixelDensity()` retrieves how many addressable pixels correspond to one unit of native coordinates.
|
|
||||||
- `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` is emitted when the value retrievable from `SDL_GetWindowSizeInPixels()` changes.
|
|
||||||
- `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` is emitted when the value retrievable from `SDL_GetWindowDisplayScale()` changes.
|
|
||||||
- Windows created with `SDL_WINDOW_HIGH_PIXEL_DENSITY` will ask the platform to display addressable pixels at their natural scale.
|
|
||||||
|
|
||||||
## Numeric example
|
|
||||||
|
|
||||||
Given a fullscreen window spanning a 3840x2160 monitor set to 2x display or 200% scaling, the following tabulates the effect of creating a window with or without `SDL_WINDOW_HIGH_PIXEL_DENSITY` on MacOS and Win32:
|
|
||||||
|
|
||||||
| Value | MacOS (Default) | MacOS (HD) | Win32 (Default & HD) |
|
|
||||||
|--------------------------------|-----------------|------------|----------------------|
|
|
||||||
| `SDL_GetWindowSize()` | 1920x1080 | 1920x1080 | 3840x2160 |
|
|
||||||
| `SDL_GetWindowSizeInPixels()` | 1920x1080 | 3840x2160 | 3840x2160 |
|
|
||||||
| `SDL_GetDisplayContentScale()` | 1.0 | 1.0 | 2.0 |
|
|
||||||
| `SDL_GetWindowDisplayScale()` | 1.0 | 2.0 | 2.0 |
|
|
||||||
| `SDL_GetWindowPixelDensity()` | 1.0 | 2.0 | 1.0 |
|
|
||||||
|
|
||||||
Observe the philosophical difference between the approaches taken by MacOS and Win32:
|
|
||||||
- Win32 coordinate system always deals in physical device pixels, high DPI support is achieved by providing an advisory hint for the developer to enlarge drawn objects. Ignoring the advisory scale factor results in graphics appearing tiny.
|
|
||||||
- MacOS coordinate system always deals in physical content sizes, high DPI support is achieved by providing an optional flag for the developer to request finer granularity. Omitting the granularity request results in graphics appearing coarse.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Displays now have a content display scale, which is the expected scale for content based on the DPI settings of the display. For example, a 4K display might have a 2.0 (200%) display scale, which means that the user expects UI elements to be twice as big on this display, to aid in readability. You can query the display content scale using `SDL_GetDisplayContentScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event.
|
Displays now have a content display scale, which is the expected scale for content based on the DPI settings of the display. For example, a 4K display might have a 2.0 (200%) display scale, which means that the user expects UI elements to be twice as big on this display, to aid in readability. You can query the display content scale using `SDL_GetDisplayContentScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event.
|
||||||
@@ -34,3 +8,33 @@ Displays now have a content display scale, which is the expected scale for conte
|
|||||||
The window size is now distinct from the window pixel size, and the ratio between the two is the window pixel density. If the window is created with the `SDL_WINDOW_HIGH_PIXEL_DENSITY` flag, SDL will try to match the native pixel density for the display, otherwise it will try to have the pixel size match the window size. You can query the window pixel density using `SDL_GetWindowPixelDensity()`. You can query the window pixel size using `SDL_GetWindowSizeInPixels()`, and when this changes you get an `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event. You are guaranteed to get a `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event when a window is created and resized, and you can use this event to create and resize your graphics context for the window.
|
The window size is now distinct from the window pixel size, and the ratio between the two is the window pixel density. If the window is created with the `SDL_WINDOW_HIGH_PIXEL_DENSITY` flag, SDL will try to match the native pixel density for the display, otherwise it will try to have the pixel size match the window size. You can query the window pixel density using `SDL_GetWindowPixelDensity()`. You can query the window pixel size using `SDL_GetWindowSizeInPixels()`, and when this changes you get an `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event. You are guaranteed to get a `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event when a window is created and resized, and you can use this event to create and resize your graphics context for the window.
|
||||||
|
|
||||||
The window has a display scale, which is the scale from the pixel resolution to the desired content size, e.g. the combination of the pixel density and the content scale. For example, a 3840x2160 window displayed at 200% on Windows, and a 1920x1080 window with the high density flag on a 2x display on macOS will both have a pixel size of 3840x2160 and a display scale of 2.0. You can query the window display scale using `SDL_GetWindowDisplayScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event.
|
The window has a display scale, which is the scale from the pixel resolution to the desired content size, e.g. the combination of the pixel density and the content scale. For example, a 3840x2160 window displayed at 200% on Windows, and a 1920x1080 window with the high density flag on a 2x display on macOS will both have a pixel size of 3840x2160 and a display scale of 2.0. You can query the window display scale using `SDL_GetWindowDisplayScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event.
|
||||||
|
|
||||||
|
## Numeric example
|
||||||
|
|
||||||
|
Given a window spanning a 3840x2160 monitor set to 2x display or 200% scaling, the following tabulates the effect of creating a window with or without `SDL_WINDOW_HIGH_PIXEL_DENSITY` on macOS and Windows:
|
||||||
|
|
||||||
|
| Value | macOS (Default) | macOS (HD) | Windows (Default & HD) |
|
||||||
|
|--------------------------------|-----------------|------------|------------------------|
|
||||||
|
| `SDL_GetWindowSize()` | 1920x1080 | 1920x1080 | 3840x2160 |
|
||||||
|
| `SDL_GetWindowSizeInPixels()` | 1920x1080 | 3840x2160 | 3840x2160 |
|
||||||
|
| `SDL_GetDisplayContentScale()` | 1.0 | 1.0 | 2.0 |
|
||||||
|
| `SDL_GetWindowDisplayScale()` | 1.0 | 2.0 | 2.0 |
|
||||||
|
| `SDL_GetWindowPixelDensity()` | 1.0 | 2.0 | 1.0 |
|
||||||
|
|
||||||
|
Observe the difference between the approaches taken by macOS and Windows:
|
||||||
|
- The Windows and Android coordinate system always deals in physical device pixels, high DPI support is achieved by providing a content scale that tells the developer to draw objects larger. Ignoring this scale factor results in graphics appearing tiny.
|
||||||
|
- The macOS and iOS coordinate system always deals in window coordinates, high DPI support is achieved by providing an optional flag for the developer to request more pixels. Omitting this flag results in graphics having low detail.
|
||||||
|
- On Linux, X11 uses a similar approach to Windows and Wayland uses a similar approach to macOS.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
Proper high DPI support takes into account both the content scale and the pixel density.
|
||||||
|
|
||||||
|
First, you'd create your window with the `SDL_WINDOW_HIGH_PIXEL_DENSITY` flag, assuming you want the highest detail possible. Then you'd get the window display scale to see how much your UI elements should be enlarged to be readable.
|
||||||
|
|
||||||
|
If you're using the SDL 2D renderer, SDL provides the function `SDL_ConvertEventToRenderCoordinates()` to convert mouse coordinates between window coordinates and rendering coordinates, and the more general functions `SDL_RenderCoordinatesFromWindow()` and `SDL_RenderCoordinatesToWindow()` to do other conversion between them.
|
||||||
|
|
||||||
|
If you're not using the 2D renderer, you can implement this yourself using `SDL_GetWindowPixelDensity()` as scale factor to convert from window coordinates to pixels.
|
||||||
|
|
||||||
|
Finally you'll want to test on both Windows and macOS if possible to make sure your high DPI support works in all environments.
|
||||||
|
|
||||||
+28
-40
@@ -1,60 +1,48 @@
|
|||||||
# Versioning
|
# Versioning
|
||||||
|
|
||||||
## Since 2.23.0
|
## Since 3.2.0
|
||||||
|
|
||||||
SDL follows an "odd/even" versioning policy, similar to GLib, GTK, Flatpak
|
SDL follows an "odd/even" versioning policy, similar to GLib, GTK, Flatpak
|
||||||
and older versions of the Linux kernel:
|
and older versions of the Linux kernel:
|
||||||
|
|
||||||
* The major version (first part) increases when backwards compatibility
|
* If the minor version (second part) and the patch version (third part) is
|
||||||
is broken, which will happen infrequently.
|
divisible by 2 (for example 3.2.6, 3.4.0), this indicates a version of
|
||||||
|
SDL that is believed to be stable and suitable for production use.
|
||||||
* If the minor version (second part) is divisible by 2
|
|
||||||
(for example 2.24.x, 2.26.x), this indicates a version of SDL that
|
|
||||||
is believed to be stable and suitable for production use.
|
|
||||||
|
|
||||||
* In stable releases, the patchlevel or micro version (third part)
|
* In stable releases, the patchlevel or micro version (third part)
|
||||||
indicates bugfix releases. Bugfix releases should not add or
|
indicates bugfix releases. Bugfix releases may add small changes
|
||||||
remove ABI, so the ".0" release (for example 2.24.0) should be
|
to the ABI, so newer patch versions are backwards-compatible but
|
||||||
forwards-compatible with all the bugfix releases from the
|
not fully forwards-compatible. For example, programs built against
|
||||||
same cycle (for example 2.24.1).
|
SDL 3.2.0 should work fine with SDL 3.2.8, but programs built against
|
||||||
|
SDL 3.2.8 may not work with 3.2.0.
|
||||||
|
|
||||||
* The minor version increases when new API or ABI is added, or when
|
* The minor version increases when significant changes are made that
|
||||||
other significant changes are made. Newer minor versions are
|
require longer development or testing time, e.g. major new functionality,
|
||||||
backwards-compatible, but not fully forwards-compatible.
|
or revamping support for a platform. Newer minor versions are
|
||||||
For example, programs built against SDL 2.24.x should work fine
|
backwards-compatible, but not fully forwards-compatible. For example,
|
||||||
with SDL 2.26.x, but programs built against SDL 2.26.x will not
|
programs built against SDL 3.2.x should work fine with SDL 3.4.x,
|
||||||
necessarily work with 2.24.x.
|
but programs built against SDL 3.4.x may not work with 3.2.x.
|
||||||
|
|
||||||
* If the minor version (second part) is not divisible by 2
|
* If the minor version (second part) or patch version (third part) is not
|
||||||
(for example 2.23.x, 2.25.x), this indicates a development prerelease
|
divisible by 2 (for example 3.2.9, 3.3.x), this indicates a development
|
||||||
of SDL that is not suitable for stable software distributions.
|
prerelease of SDL that is not suitable for stable software distributions.
|
||||||
Use with caution.
|
Use with caution.
|
||||||
|
|
||||||
* The patchlevel or micro version (third part) increases with
|
* The patchlevel or micro version (third part) increases with each prerelease.
|
||||||
each prerelease.
|
|
||||||
|
|
||||||
* Each prerelease might add new API and/or ABI.
|
|
||||||
|
|
||||||
* Prereleases are backwards-compatible with older stable branches.
|
* Prereleases are backwards-compatible with older stable branches.
|
||||||
For example, 2.25.x will be backwards-compatible with 2.24.x.
|
For example, programs built against SDL 3.2.x should work fine with
|
||||||
|
SDL 3.3.x, but programs built against SDL 3.3.x may not work with 3.2.x.
|
||||||
|
|
||||||
* Prereleases are not guaranteed to be backwards-compatible with
|
* Prereleases are not guaranteed to be backwards-compatible with each other.
|
||||||
each other. For example, new API or ABI added in 2.25.1
|
For example, new API or ABI added in 3.3.0 might be removed or changed in
|
||||||
might be removed or changed in 2.25.2.
|
3.3.1. If this would be a problem for you, please do not use prereleases.
|
||||||
If this would be a problem for you, please do not use prereleases.
|
|
||||||
|
|
||||||
* Only upgrade to a prerelease if you can guarantee that you will
|
* Only use a prerelease if you can guarantee that you will promptly upgrade
|
||||||
promptly upgrade to the stable release that follows it.
|
to the stable release that follows it. For example, do not use 3.3.x
|
||||||
For example, do not upgrade to 2.23.x unless you will be able to
|
unless you will be able to upgrade to 3.4.0 when it becomes available.
|
||||||
upgrade to 2.24.0 when it becomes available.
|
|
||||||
|
|
||||||
* Software distributions that have a freeze policy (in particular Linux
|
* Software distributions that have a freeze policy (in particular Linux
|
||||||
distributions with a release cycle, such as Debian and Fedora)
|
distributions with a release cycle, such as Debian and Fedora)
|
||||||
should usually only package stable releases, and not prereleases.
|
should only package stable releases, and not prereleases.
|
||||||
|
|
||||||
## Before 2.23.0
|
|
||||||
|
|
||||||
Older versions of SDL followed a similar policy, but instead of the
|
|
||||||
odd/even rule applying to the minor version, it applied to the patchlevel
|
|
||||||
(micro version, third part). For example, 2.0.22 was a stable release
|
|
||||||
and 2.0.21 was a prerelease.
|
|
||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main include header for the SDL library, version 3.2.10
|
* Main include header for the SDL library, version 3.2.12
|
||||||
*
|
*
|
||||||
* It is almost always best to include just this one header instead of
|
* It is almost always best to include just this one header instead of
|
||||||
* picking out individual headers included here. There are exceptions to
|
* picking out individual headers included here. There are exceptions to
|
||||||
|
|||||||
@@ -492,6 +492,8 @@ typedef struct SDL_MouseWheelEvent
|
|||||||
SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
|
SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
|
||||||
float mouse_x; /**< X coordinate, relative to window */
|
float mouse_x; /**< X coordinate, relative to window */
|
||||||
float mouse_y; /**< Y coordinate, relative to window */
|
float mouse_y; /**< Y coordinate, relative to window */
|
||||||
|
Sint32 integer_x; /**< The amount scrolled horizontally, accumulated to whole scroll "ticks" (added in 3.2.12) */
|
||||||
|
Sint32 integer_y; /**< The amount scrolled vertically, accumulated to whole scroll "ticks" (added in 3.2.12) */
|
||||||
} SDL_MouseWheelEvent;
|
} SDL_MouseWheelEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+10
-10
@@ -2467,9 +2467,9 @@ extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_CreateGPUShader(
|
|||||||
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT`: (Direct3D 12 only)
|
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT`: (Direct3D 12 only)
|
||||||
* if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, clear
|
* if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, clear
|
||||||
* the texture to a depth of this value. Defaults to zero.
|
* the texture to a depth of this value. Defaults to zero.
|
||||||
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8`: (Direct3D 12
|
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER`: (Direct3D 12
|
||||||
* only) if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET,
|
* only) if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET,
|
||||||
* clear the texture to a stencil of this value. Defaults to zero.
|
* clear the texture to a stencil of this Uint8 value. Defaults to zero.
|
||||||
* - `SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING`: a name that can be displayed
|
* - `SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING`: a name that can be displayed
|
||||||
* in debugging tools.
|
* in debugging tools.
|
||||||
*
|
*
|
||||||
@@ -2495,13 +2495,13 @@ extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL SDL_CreateGPUTexture(
|
|||||||
SDL_GPUDevice *device,
|
SDL_GPUDevice *device,
|
||||||
const SDL_GPUTextureCreateInfo *createinfo);
|
const SDL_GPUTextureCreateInfo *createinfo);
|
||||||
|
|
||||||
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT "SDL.gpu.texture.create.d3d12.clear.r"
|
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT "SDL.gpu.texture.create.d3d12.clear.r"
|
||||||
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT "SDL.gpu.texture.create.d3d12.clear.g"
|
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT "SDL.gpu.texture.create.d3d12.clear.g"
|
||||||
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT "SDL.gpu.texture.create.d3d12.clear.b"
|
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT "SDL.gpu.texture.create.d3d12.clear.b"
|
||||||
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT "SDL.gpu.texture.create.d3d12.clear.a"
|
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT "SDL.gpu.texture.create.d3d12.clear.a"
|
||||||
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT "SDL.gpu.texture.create.d3d12.clear.depth"
|
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT "SDL.gpu.texture.create.d3d12.clear.depth"
|
||||||
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8 "SDL.gpu.texture.create.d3d12.clear.stencil"
|
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER "SDL.gpu.texture.create.d3d12.clear.stencil"
|
||||||
#define SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING "SDL.gpu.texture.create.name"
|
#define SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING "SDL.gpu.texture.create.name"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a buffer object to be used in graphics or compute workflows.
|
* Creates a buffer object to be used in graphics or compute workflows.
|
||||||
@@ -3775,7 +3775,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseWindowFromGPUDevice(
|
|||||||
* supported via SDL_WindowSupportsGPUPresentMode /
|
* supported via SDL_WindowSupportsGPUPresentMode /
|
||||||
* SDL_WindowSupportsGPUSwapchainComposition prior to calling this function.
|
* SDL_WindowSupportsGPUSwapchainComposition prior to calling this function.
|
||||||
*
|
*
|
||||||
* SDL_GPU_PRESENTMODE_VSYNC and SDL_GPU_SWAPCHAINCOMPOSITION_SDR are always
|
* SDL_GPU_PRESENTMODE_VSYNC with SDL_GPU_SWAPCHAINCOMPOSITION_SDR are always
|
||||||
* supported.
|
* supported.
|
||||||
*
|
*
|
||||||
* \param device a GPU context.
|
* \param device a GPU context.
|
||||||
|
|||||||
@@ -1074,8 +1074,8 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* By default, SDL will try all available GPU backends in a reasonable order
|
* By default, SDL will try all available GPU backends in a reasonable order
|
||||||
* until it finds one that can work, but this hint allows the app or user to
|
* until it finds one that can work, but this hint allows the app or user to
|
||||||
* force a specific target, such as "direct3d11" if, say, your hardware
|
* force a specific target, such as "direct3d12" if, say, your hardware
|
||||||
* supports D3D12 but want to try using D3D11 instead.
|
* supports Vulkan but you want to try using D3D12 instead.
|
||||||
*
|
*
|
||||||
* This hint should be set before any GPU functions are called.
|
* This hint should be set before any GPU functions are called.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1607,8 +1607,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, S
|
|||||||
* Return whether an explicit rectangle was set as the viewport.
|
* Return whether an explicit rectangle was set as the viewport.
|
||||||
*
|
*
|
||||||
* This is useful if you're saving and restoring the viewport and want to know
|
* This is useful if you're saving and restoring the viewport and want to know
|
||||||
* whether you should restore a specific rectangle or NULL. Note that the
|
* whether you should restore a specific rectangle or NULL.
|
||||||
* viewport is always reset when changing rendering targets.
|
|
||||||
*
|
*
|
||||||
* Each render target has its own viewport. This function checks the viewport
|
* Each render target has its own viewport. This function checks the viewport
|
||||||
* for the current render target.
|
* for the current render target.
|
||||||
|
|||||||
@@ -5974,8 +5974,12 @@ size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
|
|||||||
size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
|
size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
/* strdup is not ANSI but POSIX, and its prototype might be hidden... */
|
/* strdup is not ANSI but POSIX, and its prototype might be hidden... */
|
||||||
|
/* not for windows: might conflict with string.h where strdup may have
|
||||||
|
* dllimport attribute: https://github.com/libsdl-org/SDL/issues/12948 */
|
||||||
char *strdup(const char *str);
|
char *strdup(const char *str);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Starting LLVM 16, the analyser errors out if these functions do not have
|
/* Starting LLVM 16, the analyser errors out if these functions do not have
|
||||||
their prototype defined (clang-diagnostic-implicit-function-declaration) */
|
their prototype defined (clang-diagnostic-implicit-function-declaration) */
|
||||||
|
|||||||
@@ -1135,9 +1135,6 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SD
|
|||||||
* If either `srcrect` or `dstrect` are NULL, the entire surface (`src` or
|
* If either `srcrect` or `dstrect` are NULL, the entire surface (`src` or
|
||||||
* `dst`) is copied while ensuring clipping to `dst->clip_rect`.
|
* `dst`) is copied while ensuring clipping to `dst->clip_rect`.
|
||||||
*
|
*
|
||||||
* The final blit rectangles are saved in `srcrect` and `dstrect` after all
|
|
||||||
* clipping is performed.
|
|
||||||
*
|
|
||||||
* The blit function should not be called on a locked surface.
|
* The blit function should not be called on a locked surface.
|
||||||
*
|
*
|
||||||
* The blit semantics for surfaces with and without blending and colorkey are
|
* The blit semantics for surfaces with and without blending and colorkey are
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* \since This macro is available since SDL 3.2.0.
|
* \since This macro is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
#define SDL_MICRO_VERSION 10
|
#define SDL_MICRO_VERSION 12
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This macro turns the version numbers into a numeric value.
|
* This macro turns the version numbers into a numeric value.
|
||||||
|
|||||||
@@ -426,10 +426,10 @@ typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void *userdata, SDL_EGLDi
|
|||||||
*/
|
*/
|
||||||
typedef enum SDL_GLAttr
|
typedef enum SDL_GLAttr
|
||||||
{
|
{
|
||||||
SDL_GL_RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 3. */
|
SDL_GL_RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 8. */
|
||||||
SDL_GL_GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 3. */
|
SDL_GL_GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 8. */
|
||||||
SDL_GL_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 2. */
|
SDL_GL_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 8. */
|
||||||
SDL_GL_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 0. */
|
SDL_GL_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 8. */
|
||||||
SDL_GL_BUFFER_SIZE, /**< the minimum number of bits for frame buffer size; defaults to 0. */
|
SDL_GL_BUFFER_SIZE, /**< the minimum number of bits for frame buffer size; defaults to 0. */
|
||||||
SDL_GL_DOUBLEBUFFER, /**< whether the output is single or double buffered; defaults to double buffering on. */
|
SDL_GL_DOUBLEBUFFER, /**< whether the output is single or double buffered; defaults to double buffering on. */
|
||||||
SDL_GL_DEPTH_SIZE, /**< the minimum number of bits in the depth buffer; defaults to 16. */
|
SDL_GL_DEPTH_SIZE, /**< the minimum number of bits in the depth buffer; defaults to 16. */
|
||||||
@@ -1041,6 +1041,10 @@ extern SDL_DECLSPEC SDL_Window ** SDLCALL SDL_GetWindows(int *count);
|
|||||||
/**
|
/**
|
||||||
* Create a window with the specified dimensions and flags.
|
* Create a window with the specified dimensions and flags.
|
||||||
*
|
*
|
||||||
|
* The window size is a request and may be different than expected based on
|
||||||
|
* the desktop layout and window manager policies. Your application should be
|
||||||
|
* prepared to handle a window of any size.
|
||||||
|
*
|
||||||
* `flags` may be any of the following OR'd together:
|
* `flags` may be any of the following OR'd together:
|
||||||
*
|
*
|
||||||
* - `SDL_WINDOW_FULLSCREEN`: fullscreen window at desktop resolution
|
* - `SDL_WINDOW_FULLSCREEN`: fullscreen window at desktop resolution
|
||||||
@@ -1127,6 +1131,10 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int
|
|||||||
/**
|
/**
|
||||||
* Create a child popup window of the specified parent window.
|
* Create a child popup window of the specified parent window.
|
||||||
*
|
*
|
||||||
|
* The window size is a request and may be different than expected based on
|
||||||
|
* the desktop layout and window manager policies. Your application should be
|
||||||
|
* prepared to handle a window of any size.
|
||||||
|
*
|
||||||
* The flags parameter **must** contain at least one of the following:
|
* The flags parameter **must** contain at least one of the following:
|
||||||
*
|
*
|
||||||
* - `SDL_WINDOW_TOOLTIP`: The popup window is a tooltip and will not pass any
|
* - `SDL_WINDOW_TOOLTIP`: The popup window is a tooltip and will not pass any
|
||||||
@@ -1189,6 +1197,10 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
|
|||||||
/**
|
/**
|
||||||
* Create a window with the specified properties.
|
* Create a window with the specified properties.
|
||||||
*
|
*
|
||||||
|
* The window size is a request and may be different than expected based on
|
||||||
|
* the desktop layout and window manager policies. Your application should be
|
||||||
|
* prepared to handle a window of any size.
|
||||||
|
*
|
||||||
* These are the supported properties:
|
* These are the supported properties:
|
||||||
*
|
*
|
||||||
* - `SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: true if the window should
|
* - `SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: true if the window should
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
|
|
||||||
#include "SDL_hints_c.h"
|
#include "SDL_hints_c.h"
|
||||||
|
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID
|
||||||
|
#include "core/android/SDL_android.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct SDL_HintWatch
|
typedef struct SDL_HintWatch
|
||||||
{
|
{
|
||||||
SDL_HintCallback callback;
|
SDL_HintCallback callback;
|
||||||
@@ -147,6 +151,13 @@ bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriori
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID
|
||||||
|
if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
|
||||||
|
// Special handling for this hint, which needs to persist outside the normal application flow
|
||||||
|
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(value, false));
|
||||||
|
}
|
||||||
|
#endif // SDL_PLATFORM_ANDROID
|
||||||
|
|
||||||
SDL_UnlockProperties(hints);
|
SDL_UnlockProperties(hints);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -185,6 +196,17 @@ bool SDL_ResetHint(const char *name)
|
|||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID
|
||||||
|
if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
|
||||||
|
// Special handling for this hint, which needs to persist outside the normal application flow
|
||||||
|
if (env) {
|
||||||
|
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(env, false));
|
||||||
|
} else {
|
||||||
|
Android_SetAllowRecreateActivity(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SDL_PLATFORM_ANDROID
|
||||||
|
|
||||||
SDL_UnlockProperties(hints);
|
SDL_UnlockProperties(hints);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -210,6 +232,17 @@ static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, c
|
|||||||
SDL_free(hint->value);
|
SDL_free(hint->value);
|
||||||
hint->value = NULL;
|
hint->value = NULL;
|
||||||
hint->priority = SDL_HINT_DEFAULT;
|
hint->priority = SDL_HINT_DEFAULT;
|
||||||
|
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID
|
||||||
|
if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
|
||||||
|
// Special handling for this hint, which needs to persist outside the normal application flow
|
||||||
|
if (env) {
|
||||||
|
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(env, false));
|
||||||
|
} else {
|
||||||
|
Android_SetAllowRecreateActivity(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SDL_PLATFORM_ANDROID
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_ResetHints(void)
|
void SDL_ResetHints(void)
|
||||||
|
|||||||
+5
-1
@@ -403,6 +403,10 @@ const char *SDL_GetPersistentString(const char *string)
|
|||||||
static int PrefixMatch(const char *a, const char *b)
|
static int PrefixMatch(const char *a, const char *b)
|
||||||
{
|
{
|
||||||
int matchlen = 0;
|
int matchlen = 0;
|
||||||
|
// Fixes the "HORI HORl Taiko No Tatsujin Drum Controller"
|
||||||
|
if (SDL_strncmp(a, "HORI ", 5) == 0 && SDL_strncmp(b, "HORl ", 5) == 0) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
while (*a && *b) {
|
while (*a && *b) {
|
||||||
if (SDL_tolower((unsigned char)*a++) == SDL_tolower((unsigned char)*b++)) {
|
if (SDL_tolower((unsigned char)*a++) == SDL_tolower((unsigned char)*b++)) {
|
||||||
++matchlen;
|
++matchlen;
|
||||||
@@ -424,8 +428,8 @@ char *SDL_CreateDeviceName(Uint16 vendor, Uint16 product, const char *vendor_nam
|
|||||||
{ "ASTRO Gaming", "ASTRO" },
|
{ "ASTRO Gaming", "ASTRO" },
|
||||||
{ "Bensussen Deutsch & Associates,Inc.(BDA)", "BDA" },
|
{ "Bensussen Deutsch & Associates,Inc.(BDA)", "BDA" },
|
||||||
{ "Guangzhou Chicken Run Network Technology Co., Ltd.", "GameSir" },
|
{ "Guangzhou Chicken Run Network Technology Co., Ltd.", "GameSir" },
|
||||||
{ "HORI CO.,LTD", "HORI" },
|
|
||||||
{ "HORI CO.,LTD.", "HORI" },
|
{ "HORI CO.,LTD.", "HORI" },
|
||||||
|
{ "HORI CO.,LTD", "HORI" },
|
||||||
{ "Mad Catz Inc.", "Mad Catz" },
|
{ "Mad Catz Inc.", "Mad Catz" },
|
||||||
{ "Nintendo Co., Ltd.", "Nintendo" },
|
{ "Nintendo Co., Ltd.", "Nintendo" },
|
||||||
{ "NVIDIA Corporation ", "" },
|
{ "NVIDIA Corporation ", "" },
|
||||||
|
|||||||
+17
-4
@@ -1503,11 +1503,24 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle)
|
|||||||
const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
|
const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
|
||||||
{
|
{
|
||||||
const char *result = NULL;
|
const char *result = NULL;
|
||||||
SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid);
|
SDL_AudioDevice *device = NULL;
|
||||||
if (device) {
|
|
||||||
result = SDL_GetPersistentString(device->name);
|
if (!SDL_GetCurrentAudioDriver()) {
|
||||||
|
SDL_SetError("Audio subsystem is not initialized");
|
||||||
|
} else {
|
||||||
|
// This does not call ObtainPhysicalAudioDevice() because the device's name never changes, so
|
||||||
|
// it doesn't have to lock the whole device. However, just to make sure the device pointer itself
|
||||||
|
// remains valid (in case the device is unplugged at the wrong moment), we hold the
|
||||||
|
// device_hash_lock while we copy the string.
|
||||||
|
SDL_LockRWLockForReading(current_audio.device_hash_lock);
|
||||||
|
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device);
|
||||||
|
if (!device) {
|
||||||
|
SDL_SetError("Invalid audio device instance ID");
|
||||||
|
} else {
|
||||||
|
result = SDL_GetPersistentString(device->name);
|
||||||
|
}
|
||||||
|
SDL_UnlockRWLock(current_audio.device_hash_lock);
|
||||||
}
|
}
|
||||||
ReleaseAudioDevice(device);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
|
|||||||
hidden->processed_bytes = 0;
|
hidden->processed_bytes = 0;
|
||||||
hidden->callback_bytes = 0;
|
hidden->callback_bytes = 0;
|
||||||
|
|
||||||
hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers);
|
hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers - 1);
|
||||||
if (!hidden->semaphore) {
|
if (!hidden->semaphore) {
|
||||||
LOGI("SDL Failed SDL_CreateSemaphore %s recording:%d", SDL_GetError(), recording);
|
LOGI("SDL Failed SDL_CreateSemaphore %s recording:%d", SDL_GetError(), recording);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1118,7 +1118,13 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
|
|||||||
|
|
||||||
stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
|
stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
|
||||||
if (!stream_name || *stream_name == '\0') {
|
if (!stream_name || *stream_name == '\0') {
|
||||||
stream_name = "Audio Stream";
|
if (app_name) {
|
||||||
|
stream_name = app_name;
|
||||||
|
} else if (app_id) {
|
||||||
|
stream_name = app_id;
|
||||||
|
} else {
|
||||||
|
stream_name = "SDL Audio Stream";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -269,9 +269,19 @@ static const char *getAppName(void)
|
|||||||
return SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING);
|
return SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ThreadedMainloopSignal(void)
|
||||||
|
{
|
||||||
|
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // alert waiting threads to unblock.
|
||||||
|
|
||||||
|
// we need to kill any SDL_SetError state; we didn't create this thread
|
||||||
|
// so its SDL TLS slot will leak otherwise, so we do this every time
|
||||||
|
// we're (presumably) losing control of the thread.
|
||||||
|
SDL_CleanupTLS();
|
||||||
|
}
|
||||||
|
|
||||||
static void OperationStateChangeCallback(pa_operation *o, void *userdata)
|
static void OperationStateChangeCallback(pa_operation *o, void *userdata)
|
||||||
{
|
{
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
|
ThreadedMainloopSignal(); // just signal any waiting code, it can look up the details.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function assume you are holding `mainloop`'s lock. The operation is unref'd in here, assuming
|
/* This function assume you are holding `mainloop`'s lock. The operation is unref'd in here, assuming
|
||||||
@@ -313,7 +323,7 @@ static void DisconnectFromPulseServer(void)
|
|||||||
|
|
||||||
static void PulseContextStateChangeCallback(pa_context *context, void *userdata)
|
static void PulseContextStateChangeCallback(pa_context *context, void *userdata)
|
||||||
{
|
{
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
|
ThreadedMainloopSignal(); // just signal any waiting code, it can look up the details.
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ConnectToPulseServer(void)
|
static bool ConnectToPulseServer(void)
|
||||||
@@ -400,7 +410,7 @@ static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata)
|
|||||||
struct SDL_PrivateAudioData *h = (struct SDL_PrivateAudioData *)userdata;
|
struct SDL_PrivateAudioData *h = (struct SDL_PrivateAudioData *)userdata;
|
||||||
//SDL_Log("PULSEAUDIO WRITE CALLBACK! nbytes=%u", (unsigned int) nbytes);
|
//SDL_Log("PULSEAUDIO WRITE CALLBACK! nbytes=%u", (unsigned int) nbytes);
|
||||||
h->bytes_requested += nbytes;
|
h->bytes_requested += nbytes;
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
ThreadedMainloopSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function waits until it is possible to write a full sound buffer
|
// This function waits until it is possible to write a full sound buffer
|
||||||
@@ -471,7 +481,7 @@ static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
|||||||
static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata)
|
static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata)
|
||||||
{
|
{
|
||||||
//SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes);
|
//SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes);
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the recording code queries what it needs, we just need to signal to end any wait
|
ThreadedMainloopSignal(); // the recording code queries what it needs, we just need to signal to end any wait
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PULSEAUDIO_WaitRecordingDevice(SDL_AudioDevice *device)
|
static bool PULSEAUDIO_WaitRecordingDevice(SDL_AudioDevice *device)
|
||||||
@@ -592,7 +602,7 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device)
|
|||||||
|
|
||||||
static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata)
|
static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata)
|
||||||
{
|
{
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
|
ThreadedMainloopSignal(); // just signal any waiting code, it can look up the details.
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||||
@@ -793,7 +803,7 @@ static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last,
|
|||||||
if (i) {
|
if (i) {
|
||||||
AddPulseAudioDevice(false, i->description, i->name, i->index, &i->sample_spec);
|
AddPulseAudioDevice(false, i->description, i->name, i->index, &i->sample_spec);
|
||||||
}
|
}
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
ThreadedMainloopSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called when PulseAudio adds a recording ("source") device.
|
// This is called when PulseAudio adds a recording ("source") device.
|
||||||
@@ -803,7 +813,7 @@ static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_la
|
|||||||
if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) {
|
if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) {
|
||||||
AddPulseAudioDevice(true, i->description, i->name, i->index, &i->sample_spec);
|
AddPulseAudioDevice(true, i->description, i->name, i->index, &i->sample_spec);
|
||||||
}
|
}
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
ThreadedMainloopSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data)
|
static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data)
|
||||||
@@ -828,7 +838,7 @@ static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *dat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
ThreadedMainloopSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata)
|
static bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata)
|
||||||
@@ -872,7 +882,7 @@ static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint3
|
|||||||
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByIndex, (void *)(uintptr_t)idx));
|
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByIndex, (void *)(uintptr_t)idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
ThreadedMainloopSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckDefaultDevice(const bool changed, char *device_path)
|
static bool CheckDefaultDevice(const bool changed, char *device_path)
|
||||||
|
|||||||
@@ -751,6 +751,8 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
|
|||||||
typedef int (*SDL_main_func)(int argc, char *argv[]);
|
typedef int (*SDL_main_func)(int argc, char *argv[]);
|
||||||
|
|
||||||
static int run_count = 0;
|
static int run_count = 0;
|
||||||
|
static bool allow_recreate_activity;
|
||||||
|
static bool allow_recreate_activity_set;
|
||||||
|
|
||||||
JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
|
JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
|
||||||
JNIEnv *env, jclass jcls)
|
JNIEnv *env, jclass jcls)
|
||||||
@@ -760,10 +762,16 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Android_SetAllowRecreateActivity(bool enabled)
|
||||||
|
{
|
||||||
|
allow_recreate_activity = enabled;
|
||||||
|
allow_recreate_activity_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(nativeAllowRecreateActivity)(
|
JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(nativeAllowRecreateActivity)(
|
||||||
JNIEnv *env, jclass jcls)
|
JNIEnv *env, jclass jcls)
|
||||||
{
|
{
|
||||||
return SDL_GetHintBoolean(SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY, false);
|
return allow_recreate_activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeInitMainThread)(
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeInitMainThread)(
|
||||||
@@ -1526,6 +1534,14 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
|
|||||||
// Note that we call setenv() directly to avoid affecting SDL environments
|
// Note that we call setenv() directly to avoid affecting SDL environments
|
||||||
setenv(utfname, utfvalue, 1); // This should NOT be SDL_setenv()
|
setenv(utfname, utfvalue, 1); // This should NOT be SDL_setenv()
|
||||||
|
|
||||||
|
if (SDL_strcmp(utfname, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
|
||||||
|
// Special handling for this hint, which needs to persist outside the normal application flow
|
||||||
|
// Only set this the first time we run, in case it's been set by the application via SDL_SetHint()
|
||||||
|
if (!allow_recreate_activity_set) {
|
||||||
|
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(utfvalue, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(*env)->ReleaseStringUTFChars(env, name, utfname);
|
(*env)->ReleaseStringUTFChars(env, name, utfname);
|
||||||
(*env)->ReleaseStringUTFChars(env, value, utfvalue);
|
(*env)->ReleaseStringUTFChars(env, value, utfvalue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ bool Android_WaitLifecycleEvent(SDL_AndroidLifecycleEvent *event, Sint64 timeout
|
|||||||
void Android_LockActivityMutex(void);
|
void Android_LockActivityMutex(void);
|
||||||
void Android_UnlockActivityMutex(void);
|
void Android_UnlockActivityMutex(void);
|
||||||
|
|
||||||
|
void Android_SetAllowRecreateActivity(bool enabled);
|
||||||
|
|
||||||
// Interface from the SDL library into the Android Java activity
|
// Interface from the SDL library into the Android Java activity
|
||||||
extern void Android_JNI_SetActivityTitle(const char *title);
|
extern void Android_JNI_SetActivityTitle(const char *title);
|
||||||
extern void Android_JNI_SetWindowStyle(bool fullscreen);
|
extern void Android_JNI_SetWindowStyle(bool fullscreen);
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 3,2,10,0
|
FILEVERSION 3,2,12,0
|
||||||
PRODUCTVERSION 3,2,10,0
|
PRODUCTVERSION 3,2,12,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
FILEFLAGS 0x0L
|
FILEFLAGS 0x0L
|
||||||
FILEOS 0x40004L
|
FILEOS 0x40004L
|
||||||
@@ -23,12 +23,12 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "\0"
|
VALUE "CompanyName", "\0"
|
||||||
VALUE "FileDescription", "SDL\0"
|
VALUE "FileDescription", "SDL\0"
|
||||||
VALUE "FileVersion", "3, 2, 10, 0\0"
|
VALUE "FileVersion", "3, 2, 12, 0\0"
|
||||||
VALUE "InternalName", "SDL\0"
|
VALUE "InternalName", "SDL\0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
|
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
|
||||||
VALUE "OriginalFilename", "SDL3.dll\0"
|
VALUE "OriginalFilename", "SDL3.dll\0"
|
||||||
VALUE "ProductName", "Simple DirectMedia Layer\0"
|
VALUE "ProductName", "Simple DirectMedia Layer\0"
|
||||||
VALUE "ProductVersion", "3, 2, 10, 0\0"
|
VALUE "ProductVersion", "3, 2, 12, 0\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|||||||
@@ -27,6 +27,35 @@
|
|||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import <UniformTypeIdentifiers/UTType.h>
|
#import <UniformTypeIdentifiers/UTType.h>
|
||||||
|
|
||||||
|
static void AddFileExtensionType(NSMutableArray *types, const char *pattern_ptr)
|
||||||
|
{
|
||||||
|
if (!*pattern_ptr) {
|
||||||
|
return; // in case the string had an extra ';' at the end.
|
||||||
|
}
|
||||||
|
|
||||||
|
// -[UTType typeWithFilenameExtension] will return nil if there's a period in the string. It's better to
|
||||||
|
// allow too many files than not allow the one the user actually needs, so just take the part after the '.'
|
||||||
|
const char *dot = SDL_strrchr(pattern_ptr, '.');
|
||||||
|
NSString *extstr = [NSString stringWithFormat: @"%s", dot ? (dot + 1) : pattern_ptr];
|
||||||
|
if (@available(macOS 11.0, *)) {
|
||||||
|
UTType *uttype = [UTType typeWithFilenameExtension:extstr];
|
||||||
|
if (uttype) { // still failed? Don't add the pattern. This is what the pre-macOS11 path does internally anyhow.
|
||||||
|
[types addObject:uttype];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[types addObject:extstr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReactivateAfterDialog(void)
|
||||||
|
{
|
||||||
|
for (NSRunningApplication *i in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
|
||||||
|
[i activateWithOptions:0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
|
}
|
||||||
|
|
||||||
void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
|
void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
|
||||||
{
|
{
|
||||||
SDL_Window* window = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL);
|
SDL_Window* window = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL);
|
||||||
@@ -87,7 +116,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
|
|||||||
|
|
||||||
if (filters) {
|
if (filters) {
|
||||||
// On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString
|
// On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString
|
||||||
NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters ];
|
NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters];
|
||||||
|
|
||||||
int has_all_files = 0;
|
int has_all_files = 0;
|
||||||
for (int i = 0; i < nfilters; i++) {
|
for (int i = 0; i < nfilters; i++) {
|
||||||
@@ -102,21 +131,14 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
|
|||||||
for (char *c = pattern; *c; c++) {
|
for (char *c = pattern; *c; c++) {
|
||||||
if (*c == ';') {
|
if (*c == ';') {
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
if(@available(macOS 11.0, *)) {
|
AddFileExtensionType(types, pattern_ptr);
|
||||||
[types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]];
|
|
||||||
} else {
|
|
||||||
[types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]];
|
|
||||||
}
|
|
||||||
pattern_ptr = c + 1;
|
pattern_ptr = c + 1;
|
||||||
} else if (*c == '*') {
|
} else if (*c == '*') {
|
||||||
has_all_files = 1;
|
has_all_files = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(@available(macOS 11.0, *)) {
|
|
||||||
[types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]];
|
AddFileExtensionType(types, pattern_ptr); // get the last piece of the string.
|
||||||
} else {
|
|
||||||
[types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]];
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_free(pattern);
|
SDL_free(pattern);
|
||||||
}
|
}
|
||||||
@@ -163,6 +185,8 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
|
|||||||
const char *files[1] = { NULL };
|
const char *files[1] = { NULL };
|
||||||
callback(userdata, files, -1);
|
callback(userdata, files, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReactivateAfterDialog();
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
if ([dialog runModal] == NSModalResponseOK) {
|
if ([dialog runModal] == NSModalResponseOK) {
|
||||||
@@ -182,6 +206,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
|
|||||||
const char *files[1] = { NULL };
|
const char *files[1] = { NULL };
|
||||||
callback(userdata, files, -1);
|
callback(userdata, files, -1);
|
||||||
}
|
}
|
||||||
|
ReactivateAfterDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -516,6 +516,14 @@ static void ShowFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_
|
|||||||
|
|
||||||
filters_str = win_get_filters(filters, nfilters);
|
filters_str = win_get_filters(filters, nfilters);
|
||||||
|
|
||||||
|
DWORD flags = 0;
|
||||||
|
if (allow_many) {
|
||||||
|
flags |= OFN_ALLOWMULTISELECT;
|
||||||
|
}
|
||||||
|
if (is_save) {
|
||||||
|
flags |= OFN_OVERWRITEPROMPT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!filters_str && filters) {
|
if (!filters_str && filters) {
|
||||||
callback(userdata, NULL, -1);
|
callback(userdata, NULL, -1);
|
||||||
SDL_free(args);
|
SDL_free(args);
|
||||||
@@ -526,7 +534,7 @@ static void ShowFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_
|
|||||||
args->filters_str = filters_str;
|
args->filters_str = filters_str;
|
||||||
args->default_file = default_location ? SDL_strdup(default_location) : NULL;
|
args->default_file = default_location ? SDL_strdup(default_location) : NULL;
|
||||||
args->parent = window;
|
args->parent = window;
|
||||||
args->flags = allow_many ? OFN_ALLOWMULTISELECT : 0;
|
args->flags = flags;
|
||||||
args->callback = callback;
|
args->callback = callback;
|
||||||
args->userdata = userdata;
|
args->userdata = userdata;
|
||||||
args->title = title ? SDL_strdup(title) : NULL;
|
args->title = title ? SDL_strdup(title) : NULL;
|
||||||
|
|||||||
@@ -633,9 +633,10 @@ static void SDL_LogEvent(const SDL_Event *event)
|
|||||||
#undef PRINT_MBUTTON_EVENT
|
#undef PRINT_MBUTTON_EVENT
|
||||||
|
|
||||||
SDL_EVENT_CASE(SDL_EVENT_MOUSE_WHEEL)
|
SDL_EVENT_CASE(SDL_EVENT_MOUSE_WHEEL)
|
||||||
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u x=%g y=%g direction=%s)",
|
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u x=%g y=%g integer_x=%d integer_y=%d direction=%s)",
|
||||||
(uint)event->wheel.timestamp, (uint)event->wheel.windowID,
|
(uint)event->wheel.timestamp, (uint)event->wheel.windowID,
|
||||||
(uint)event->wheel.which, event->wheel.x, event->wheel.y,
|
(uint)event->wheel.which, event->wheel.x, event->wheel.y,
|
||||||
|
(int)event->wheel.integer_x, (int)event->wheel.integer_y,
|
||||||
event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
|
event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1379,9 +1380,7 @@ bool SDL_RunOnMainThread(SDL_MainThreadCallback callback, void *userdata, bool w
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum wait of 30 seconds to prevent deadlocking forever
|
SDL_WaitSemaphore(entry->semaphore);
|
||||||
const Sint32 MAX_CALLBACK_WAIT = 30 * 1000;
|
|
||||||
SDL_WaitSemaphoreTimeout(entry->semaphore, MAX_CALLBACK_WAIT);
|
|
||||||
|
|
||||||
switch (SDL_GetAtomicInt(&entry->state)) {
|
switch (SDL_GetAtomicInt(&entry->state)) {
|
||||||
case SDL_MAIN_CALLBACK_COMPLETE:
|
case SDL_MAIN_CALLBACK_COMPLETE:
|
||||||
@@ -1823,7 +1822,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled)
|
|||||||
Uint8 lo = (type & 0xff);
|
Uint8 lo = (type & 0xff);
|
||||||
|
|
||||||
if (SDL_disabled_events[hi] &&
|
if (SDL_disabled_events[hi] &&
|
||||||
(SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) {
|
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
|
||||||
current_state = false;
|
current_state = false;
|
||||||
} else {
|
} else {
|
||||||
current_state = true;
|
current_state = true;
|
||||||
@@ -1832,7 +1831,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled)
|
|||||||
if ((enabled != false) != current_state) {
|
if ((enabled != false) != current_state) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
SDL_assert(SDL_disabled_events[hi] != NULL);
|
SDL_assert(SDL_disabled_events[hi] != NULL);
|
||||||
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1 << (lo & 31));
|
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1U << (lo & 31));
|
||||||
|
|
||||||
// Gamepad events depend on joystick events
|
// Gamepad events depend on joystick events
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -1863,7 +1862,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled)
|
|||||||
}
|
}
|
||||||
// Out of memory, nothing we can do...
|
// Out of memory, nothing we can do...
|
||||||
if (SDL_disabled_events[hi]) {
|
if (SDL_disabled_events[hi]) {
|
||||||
SDL_disabled_events[hi]->bits[lo / 32] |= (1 << (lo & 31));
|
SDL_disabled_events[hi]->bits[lo / 32] |= (1U << (lo & 31));
|
||||||
SDL_FlushEvent(type);
|
SDL_FlushEvent(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1882,7 +1881,7 @@ bool SDL_EventEnabled(Uint32 type)
|
|||||||
Uint8 lo = (type & 0xff);
|
Uint8 lo = (type & 0xff);
|
||||||
|
|
||||||
if (SDL_disabled_events[hi] &&
|
if (SDL_disabled_events[hi] &&
|
||||||
(SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) {
|
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+19
-8
@@ -1022,18 +1022,14 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI
|
|||||||
SDL_SetMouseFocus(window);
|
SDL_SetMouseFocus(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate fractional wheel motion if integer mode is enabled
|
|
||||||
if (mouse->integer_mode_flags & 2) {
|
|
||||||
mouse->integer_mode_residual_scroll_x = SDL_modff(mouse->integer_mode_residual_scroll_x + x, &x);
|
|
||||||
mouse->integer_mode_residual_scroll_y = SDL_modff(mouse->integer_mode_residual_scroll_y + y, &y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x == 0.0f && y == 0.0f) {
|
if (x == 0.0f && y == 0.0f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post the event, if desired
|
// Post the event, if desired
|
||||||
if (SDL_EventEnabled(SDL_EVENT_MOUSE_WHEEL)) {
|
if (SDL_EventEnabled(SDL_EVENT_MOUSE_WHEEL)) {
|
||||||
|
float integer_x, integer_y;
|
||||||
|
|
||||||
if (!mouse->relative_mode || mouse->warp_emulation_active) {
|
if (!mouse->relative_mode || mouse->warp_emulation_active) {
|
||||||
// We're not in relative mode, so all mouse events are global mouse events
|
// We're not in relative mode, so all mouse events are global mouse events
|
||||||
mouseID = SDL_GLOBAL_MOUSE_ID;
|
mouseID = SDL_GLOBAL_MOUSE_ID;
|
||||||
@@ -1044,11 +1040,26 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI
|
|||||||
event.common.timestamp = timestamp;
|
event.common.timestamp = timestamp;
|
||||||
event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
|
event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
|
||||||
event.wheel.which = mouseID;
|
event.wheel.which = mouseID;
|
||||||
event.wheel.x = x;
|
|
||||||
event.wheel.y = y;
|
|
||||||
event.wheel.direction = direction;
|
event.wheel.direction = direction;
|
||||||
event.wheel.mouse_x = mouse->x;
|
event.wheel.mouse_x = mouse->x;
|
||||||
event.wheel.mouse_y = mouse->y;
|
event.wheel.mouse_y = mouse->y;
|
||||||
|
|
||||||
|
mouse->residual_scroll_x = SDL_modff(mouse->residual_scroll_x + x, &integer_x);
|
||||||
|
event.wheel.integer_x = (Sint32)integer_x;
|
||||||
|
|
||||||
|
mouse->residual_scroll_y = SDL_modff(mouse->residual_scroll_y + y, &integer_y);
|
||||||
|
event.wheel.integer_y = (Sint32)integer_y;
|
||||||
|
|
||||||
|
// Return the accumulated values in x/y when integer wheel mode is enabled.
|
||||||
|
// This is necessary for compatibility with sdl2-compat 2.32.54.
|
||||||
|
if (mouse->integer_mode_flags & 2) {
|
||||||
|
event.wheel.x = integer_x;
|
||||||
|
event.wheel.y = integer_y;
|
||||||
|
} else {
|
||||||
|
event.wheel.x = x;
|
||||||
|
event.wheel.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,8 +95,6 @@ typedef struct
|
|||||||
Uint8 integer_mode_flags; // 1 to enable mouse quantization, 2 to enable wheel quantization
|
Uint8 integer_mode_flags; // 1 to enable mouse quantization, 2 to enable wheel quantization
|
||||||
float integer_mode_residual_motion_x;
|
float integer_mode_residual_motion_x;
|
||||||
float integer_mode_residual_motion_y;
|
float integer_mode_residual_motion_y;
|
||||||
float integer_mode_residual_scroll_x;
|
|
||||||
float integer_mode_residual_scroll_y;
|
|
||||||
|
|
||||||
// Data common to all mice
|
// Data common to all mice
|
||||||
SDL_Window *focus;
|
SDL_Window *focus;
|
||||||
@@ -105,6 +103,8 @@ typedef struct
|
|||||||
float x_accu;
|
float x_accu;
|
||||||
float y_accu;
|
float y_accu;
|
||||||
float last_x, last_y; // the last reported x and y coordinates
|
float last_x, last_y; // the last reported x and y coordinates
|
||||||
|
float residual_scroll_x;
|
||||||
|
float residual_scroll_y;
|
||||||
double click_motion_x;
|
double click_motion_x;
|
||||||
double click_motion_y;
|
double click_motion_y;
|
||||||
bool has_position;
|
bool has_position;
|
||||||
|
|||||||
+11
-2
@@ -565,10 +565,19 @@ void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
|
|||||||
event.pbutton.down = down;
|
event.pbutton.down = down;
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
|
|
||||||
if (window && (pen_touching == instance_id)) {
|
if (window && (!pen_touching || (pen_touching == instance_id))) {
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
if (mouse && mouse->pen_mouse_events) {
|
if (mouse && mouse->pen_mouse_events) {
|
||||||
SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, button + 1, down);
|
static const Uint8 mouse_buttons[] = {
|
||||||
|
SDL_BUTTON_LEFT,
|
||||||
|
SDL_BUTTON_RIGHT,
|
||||||
|
SDL_BUTTON_MIDDLE,
|
||||||
|
SDL_BUTTON_X1,
|
||||||
|
SDL_BUTTON_X2
|
||||||
|
};
|
||||||
|
if (button < SDL_arraysize(mouse_buttons)) {
|
||||||
|
SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, mouse_buttons[button], down);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-2
@@ -56,11 +56,43 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_RENDERPASS \
|
#define CHECK_RENDERPASS \
|
||||||
if (!((Pass *)render_pass)->in_progress) { \
|
if (!((RenderPass *)render_pass)->in_progress) { \
|
||||||
SDL_assert_release(!"Render pass not in progress!"); \
|
SDL_assert_release(!"Render pass not in progress!"); \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHECK_SAMPLER_TEXTURES \
|
||||||
|
RenderPass *rp = (RenderPass *)render_pass; \
|
||||||
|
for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \
|
||||||
|
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
|
||||||
|
if (rp->color_targets[color_target_index] == texture_sampler_bindings[texture_sampler_index].texture) { \
|
||||||
|
SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a sampler!"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
|
||||||
|
if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == texture_sampler_bindings[texture_sampler_index].texture) { \
|
||||||
|
SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a sampler!"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_STORAGE_TEXTURES \
|
||||||
|
RenderPass *rp = (RenderPass *)render_pass; \
|
||||||
|
for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \
|
||||||
|
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
|
||||||
|
if (rp->color_targets[color_target_index] == storage_textures[texture_sampler_index]) { \
|
||||||
|
SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a storage texture!"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
|
||||||
|
if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == storage_textures[texture_sampler_index]) { \
|
||||||
|
SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a storage texture!"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define CHECK_GRAPHICS_PIPELINE_BOUND \
|
#define CHECK_GRAPHICS_PIPELINE_BOUND \
|
||||||
if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \
|
if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \
|
||||||
SDL_assert_release(!"Graphics pipeline not bound!"); \
|
SDL_assert_release(!"Graphics pipeline not bound!"); \
|
||||||
@@ -137,7 +169,7 @@
|
|||||||
((CommandBufferCommonHeader *)command_buffer)->device
|
((CommandBufferCommonHeader *)command_buffer)->device
|
||||||
|
|
||||||
#define RENDERPASS_COMMAND_BUFFER \
|
#define RENDERPASS_COMMAND_BUFFER \
|
||||||
((Pass *)render_pass)->command_buffer
|
((RenderPass *)render_pass)->command_buffer
|
||||||
|
|
||||||
#define RENDERPASS_DEVICE \
|
#define RENDERPASS_DEVICE \
|
||||||
((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device
|
((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device
|
||||||
@@ -1523,6 +1555,13 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
|
|||||||
|
|
||||||
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
||||||
commandBufferHeader->render_pass.in_progress = true;
|
commandBufferHeader->render_pass.in_progress = true;
|
||||||
|
for (Uint32 i = 0; i < num_color_targets; i += 1) {
|
||||||
|
commandBufferHeader->render_pass.color_targets[i] = color_target_infos[i].texture;
|
||||||
|
}
|
||||||
|
commandBufferHeader->render_pass.num_color_targets = num_color_targets;
|
||||||
|
if (depth_stencil_target_info != NULL) {
|
||||||
|
commandBufferHeader->render_pass.depth_stencil_target = depth_stencil_target_info->texture;
|
||||||
|
}
|
||||||
return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass);
|
return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1696,6 +1735,7 @@ void SDL_BindGPUVertexSamplers(
|
|||||||
|
|
||||||
if (RENDERPASS_DEVICE->debug_mode) {
|
if (RENDERPASS_DEVICE->debug_mode) {
|
||||||
CHECK_RENDERPASS
|
CHECK_RENDERPASS
|
||||||
|
CHECK_SAMPLER_TEXTURES
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDERPASS_DEVICE->BindVertexSamplers(
|
RENDERPASS_DEVICE->BindVertexSamplers(
|
||||||
@@ -1722,6 +1762,7 @@ void SDL_BindGPUVertexStorageTextures(
|
|||||||
|
|
||||||
if (RENDERPASS_DEVICE->debug_mode) {
|
if (RENDERPASS_DEVICE->debug_mode) {
|
||||||
CHECK_RENDERPASS
|
CHECK_RENDERPASS
|
||||||
|
CHECK_STORAGE_TEXTURES
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDERPASS_DEVICE->BindVertexStorageTextures(
|
RENDERPASS_DEVICE->BindVertexStorageTextures(
|
||||||
@@ -1774,6 +1815,7 @@ void SDL_BindGPUFragmentSamplers(
|
|||||||
|
|
||||||
if (RENDERPASS_DEVICE->debug_mode) {
|
if (RENDERPASS_DEVICE->debug_mode) {
|
||||||
CHECK_RENDERPASS
|
CHECK_RENDERPASS
|
||||||
|
CHECK_SAMPLER_TEXTURES
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDERPASS_DEVICE->BindFragmentSamplers(
|
RENDERPASS_DEVICE->BindFragmentSamplers(
|
||||||
@@ -1800,6 +1842,7 @@ void SDL_BindGPUFragmentStorageTextures(
|
|||||||
|
|
||||||
if (RENDERPASS_DEVICE->debug_mode) {
|
if (RENDERPASS_DEVICE->debug_mode) {
|
||||||
CHECK_RENDERPASS
|
CHECK_RENDERPASS
|
||||||
|
CHECK_STORAGE_TEXTURES
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDERPASS_DEVICE->BindFragmentStorageTextures(
|
RENDERPASS_DEVICE->BindFragmentStorageTextures(
|
||||||
@@ -1960,6 +2003,12 @@ void SDL_EndGPURenderPass(
|
|||||||
|
|
||||||
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
|
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
|
||||||
commandBufferCommonHeader->render_pass.in_progress = false;
|
commandBufferCommonHeader->render_pass.in_progress = false;
|
||||||
|
for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
|
||||||
|
{
|
||||||
|
commandBufferCommonHeader->render_pass.color_targets[i] = NULL;
|
||||||
|
}
|
||||||
|
commandBufferCommonHeader->render_pass.num_color_targets = 0;
|
||||||
|
commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
|
||||||
commandBufferCommonHeader->graphics_pipeline_bound = false;
|
commandBufferCommonHeader->graphics_pipeline_bound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-16
@@ -24,6 +24,21 @@
|
|||||||
#ifndef SDL_GPU_DRIVER_H
|
#ifndef SDL_GPU_DRIVER_H
|
||||||
#define SDL_GPU_DRIVER_H
|
#define SDL_GPU_DRIVER_H
|
||||||
|
|
||||||
|
// GraphicsDevice Limits
|
||||||
|
|
||||||
|
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
|
||||||
|
#define MAX_STORAGE_TEXTURES_PER_STAGE 8
|
||||||
|
#define MAX_STORAGE_BUFFERS_PER_STAGE 8
|
||||||
|
#define MAX_UNIFORM_BUFFERS_PER_STAGE 4
|
||||||
|
#define MAX_COMPUTE_WRITE_TEXTURES 8
|
||||||
|
#define MAX_COMPUTE_WRITE_BUFFERS 8
|
||||||
|
#define UNIFORM_BUFFER_SIZE 32768
|
||||||
|
#define MAX_VERTEX_BUFFERS 16
|
||||||
|
#define MAX_VERTEX_ATTRIBUTES 16
|
||||||
|
#define MAX_COLOR_TARGET_BINDINGS 4
|
||||||
|
#define MAX_PRESENT_COUNT 16
|
||||||
|
#define MAX_FRAMES_IN_FLIGHT 3
|
||||||
|
|
||||||
// Common Structs
|
// Common Structs
|
||||||
|
|
||||||
typedef struct Pass
|
typedef struct Pass
|
||||||
@@ -32,10 +47,19 @@ typedef struct Pass
|
|||||||
bool in_progress;
|
bool in_progress;
|
||||||
} Pass;
|
} Pass;
|
||||||
|
|
||||||
|
typedef struct RenderPass
|
||||||
|
{
|
||||||
|
SDL_GPUCommandBuffer *command_buffer;
|
||||||
|
bool in_progress;
|
||||||
|
SDL_GPUTexture *color_targets[MAX_COLOR_TARGET_BINDINGS];
|
||||||
|
Uint32 num_color_targets;
|
||||||
|
SDL_GPUTexture *depth_stencil_target;
|
||||||
|
} RenderPass;
|
||||||
|
|
||||||
typedef struct CommandBufferCommonHeader
|
typedef struct CommandBufferCommonHeader
|
||||||
{
|
{
|
||||||
SDL_GPUDevice *device;
|
SDL_GPUDevice *device;
|
||||||
Pass render_pass;
|
RenderPass render_pass;
|
||||||
bool graphics_pipeline_bound;
|
bool graphics_pipeline_bound;
|
||||||
Pass compute_pass;
|
Pass compute_pass;
|
||||||
bool compute_pipeline_bound;
|
bool compute_pipeline_bound;
|
||||||
@@ -385,21 +409,6 @@ static inline Uint32 BytesPerRow(
|
|||||||
return blocksPerRow * SDL_GPUTextureFormatTexelBlockSize(format);
|
return blocksPerRow * SDL_GPUTextureFormatTexelBlockSize(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphicsDevice Limits
|
|
||||||
|
|
||||||
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
|
|
||||||
#define MAX_STORAGE_TEXTURES_PER_STAGE 8
|
|
||||||
#define MAX_STORAGE_BUFFERS_PER_STAGE 8
|
|
||||||
#define MAX_UNIFORM_BUFFERS_PER_STAGE 4
|
|
||||||
#define MAX_COMPUTE_WRITE_TEXTURES 8
|
|
||||||
#define MAX_COMPUTE_WRITE_BUFFERS 8
|
|
||||||
#define UNIFORM_BUFFER_SIZE 32768
|
|
||||||
#define MAX_VERTEX_BUFFERS 16
|
|
||||||
#define MAX_VERTEX_ATTRIBUTES 16
|
|
||||||
#define MAX_COLOR_TARGET_BINDINGS 4
|
|
||||||
#define MAX_PRESENT_COUNT 16
|
|
||||||
#define MAX_FRAMES_IN_FLIGHT 3
|
|
||||||
|
|
||||||
// Internal Macros
|
// Internal Macros
|
||||||
|
|
||||||
#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \
|
#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \
|
||||||
|
|||||||
+154
-30
@@ -475,6 +475,115 @@ static DXGI_FORMAT SDLToD3D12_DepthFormat[] = {
|
|||||||
};
|
};
|
||||||
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_DepthFormat, SDL_arraysize(SDLToD3D12_DepthFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_DepthFormat, SDL_arraysize(SDLToD3D12_DepthFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
||||||
|
|
||||||
|
static DXGI_FORMAT SDLToD3D12_TypelessFormat[] = {
|
||||||
|
DXGI_FORMAT_UNKNOWN, // INVALID
|
||||||
|
DXGI_FORMAT_UNKNOWN, // A8_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R10G10B10A2_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // B5G6R5_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // B5G5R5A1_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // B4G4R4A4_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC1_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC2_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC3_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC4_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC5_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC7_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC6H_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC6H_UFLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8_SNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8_SNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_SNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16_SNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16_SNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_SNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32G32_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R11G11B10_UFLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32G32_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32G32_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_INT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC1_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC2_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC3_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // BC7_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_R16_TYPELESS, // D16_UNORM
|
||||||
|
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM
|
||||||
|
DXGI_FORMAT_R32_TYPELESS, // D32_FLOAT
|
||||||
|
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM_S8_UINT
|
||||||
|
DXGI_FORMAT_R32G8X24_TYPELESS, // D32_FLOAT_S8_UINT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
|
||||||
|
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
|
||||||
|
};
|
||||||
|
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TypelessFormat, SDL_arraysize(SDLToD3D12_TypelessFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
||||||
|
|
||||||
static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
|
static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
|
||||||
D3D12_COMPARISON_FUNC_NEVER, // INVALID
|
D3D12_COMPARISON_FUNC_NEVER, // INVALID
|
||||||
D3D12_COMPARISON_FUNC_NEVER, // NEVER
|
D3D12_COMPARISON_FUNC_NEVER, // NEVER
|
||||||
@@ -3188,6 +3297,10 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
|
|||||||
D3D12_CLEAR_VALUE clearValue;
|
D3D12_CLEAR_VALUE clearValue;
|
||||||
DXGI_FORMAT format;
|
DXGI_FORMAT format;
|
||||||
bool useClearValue = false;
|
bool useClearValue = false;
|
||||||
|
bool needsSRV =
|
||||||
|
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) ||
|
||||||
|
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) ||
|
||||||
|
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ);
|
||||||
bool needsUAV =
|
bool needsUAV =
|
||||||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
|
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
|
||||||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE);
|
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE);
|
||||||
@@ -3207,6 +3320,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
|
|||||||
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
|
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
|
||||||
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||||
useClearValue = true;
|
useClearValue = true;
|
||||||
|
clearValue.Format = format;
|
||||||
clearValue.Color[0] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT, 0);
|
clearValue.Color[0] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT, 0);
|
||||||
clearValue.Color[1] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT, 0);
|
clearValue.Color[1] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT, 0);
|
||||||
clearValue.Color[2] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT, 0);
|
clearValue.Color[2] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT, 0);
|
||||||
@@ -3216,9 +3330,10 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
|
|||||||
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
|
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
|
||||||
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||||
useClearValue = true;
|
useClearValue = true;
|
||||||
|
clearValue.Format = SDLToD3D12_DepthFormat[createinfo->format];
|
||||||
clearValue.DepthStencil.Depth = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT, 0);
|
clearValue.DepthStencil.Depth = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT, 0);
|
||||||
clearValue.DepthStencil.Stencil = (UINT8)SDL_GetNumberProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8, 0);
|
clearValue.DepthStencil.Stencil = (UINT8)SDL_GetNumberProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER, 0);
|
||||||
format = SDLToD3D12_DepthFormat[createinfo->format];
|
format = needsSRV ? SDLToD3D12_TypelessFormat[createinfo->format] : SDLToD3D12_DepthFormat[createinfo->format];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsUAV) {
|
if (needsUAV) {
|
||||||
@@ -3260,7 +3375,6 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialState = isSwapchainTexture ? D3D12_RESOURCE_STATE_PRESENT : D3D12_INTERNAL_DefaultTextureResourceState(createinfo->usage);
|
initialState = isSwapchainTexture ? D3D12_RESOURCE_STATE_PRESENT : D3D12_INTERNAL_DefaultTextureResourceState(createinfo->usage);
|
||||||
clearValue.Format = desc.Format;
|
|
||||||
|
|
||||||
res = ID3D12Device_CreateCommittedResource(
|
res = ID3D12Device_CreateCommittedResource(
|
||||||
renderer->device,
|
renderer->device,
|
||||||
@@ -3280,9 +3394,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
|
|||||||
texture->resource = handle;
|
texture->resource = handle;
|
||||||
|
|
||||||
// Create the SRV if applicable
|
// Create the SRV if applicable
|
||||||
if ((createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) ||
|
if (needsSRV) {
|
||||||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) ||
|
|
||||||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) {
|
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||||
|
|
||||||
D3D12_INTERNAL_AssignStagingDescriptorHandle(
|
D3D12_INTERNAL_AssignStagingDescriptorHandle(
|
||||||
@@ -3483,7 +3595,9 @@ static SDL_GPUTexture *D3D12_CreateTexture(
|
|||||||
// Copy properties so we don't lose information when the client destroys them
|
// Copy properties so we don't lose information when the client destroys them
|
||||||
container->header.info = *createinfo;
|
container->header.info = *createinfo;
|
||||||
container->header.info.props = SDL_CreateProperties();
|
container->header.info.props = SDL_CreateProperties();
|
||||||
SDL_CopyProperties(createinfo->props, container->header.info.props);
|
if (createinfo->props) {
|
||||||
|
SDL_CopyProperties(createinfo->props, container->header.info.props);
|
||||||
|
}
|
||||||
|
|
||||||
container->textureCapacity = 1;
|
container->textureCapacity = 1;
|
||||||
container->textureCount = 1;
|
container->textureCount = 1;
|
||||||
@@ -8100,8 +8214,7 @@ static void D3D12_INTERNAL_InitBlitResources(
|
|||||||
shaderCreateInfo.code = (Uint8 *)D3D12_FullscreenVert;
|
shaderCreateInfo.code = (Uint8 *)D3D12_FullscreenVert;
|
||||||
shaderCreateInfo.code_size = sizeof(D3D12_FullscreenVert);
|
shaderCreateInfo.code_size = sizeof(D3D12_FullscreenVert);
|
||||||
shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
|
shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
|
||||||
shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
|
shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXIL;
|
||||||
shaderCreateInfo.entrypoint = "main";
|
|
||||||
|
|
||||||
renderer->blitVertexShader = D3D12_CreateShader(
|
renderer->blitVertexShader = D3D12_CreateShader(
|
||||||
(SDL_GPURenderer *)renderer,
|
(SDL_GPURenderer *)renderer,
|
||||||
@@ -8338,38 +8451,38 @@ static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) && defined(HAVE_IDXGIINFOQUEUE)
|
#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) && defined(HAVE_IDXGIINFOQUEUE)
|
||||||
static void D3D12_INTERNAL_TryInitializeDXGIDebug(D3D12Renderer *renderer)
|
static bool D3D12_INTERNAL_TryInitializeDXGIDebug(D3D12Renderer *renderer)
|
||||||
{
|
{
|
||||||
PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc;
|
PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc;
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
|
|
||||||
renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL);
|
renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL);
|
||||||
if (renderer->dxgidebug_dll == NULL) {
|
if (renderer->dxgidebug_dll == NULL) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not find " DXGIDEBUG_DLL);
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction(
|
DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction(
|
||||||
renderer->dxgidebug_dll,
|
renderer->dxgidebug_dll,
|
||||||
DXGI_GET_DEBUG_INTERFACE_FUNC);
|
DXGI_GET_DEBUG_INTERFACE_FUNC);
|
||||||
if (DXGIGetDebugInterfaceFunc == NULL) {
|
if (DXGIGetDebugInterfaceFunc == NULL) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC);
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug);
|
res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug);
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIDebug interface");
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
|
res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIInfoQueue interface");
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
|
static bool D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
|
||||||
{
|
{
|
||||||
PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterfaceFunc;
|
PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterfaceFunc;
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
@@ -8378,21 +8491,20 @@ static void D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
|
|||||||
renderer->d3d12_dll,
|
renderer->d3d12_dll,
|
||||||
D3D12_GET_DEBUG_INTERFACE_FUNC);
|
D3D12_GET_DEBUG_INTERFACE_FUNC);
|
||||||
if (D3D12GetDebugInterfaceFunc == NULL) {
|
if (D3D12GetDebugInterfaceFunc == NULL) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " D3D12_GET_DEBUG_INTERFACE_FUNC);
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = D3D12GetDebugInterfaceFunc(D3D_GUID(D3D_IID_ID3D12Debug), (void **)&renderer->d3d12Debug);
|
res = D3D12GetDebugInterfaceFunc(D3D_GUID(D3D_IID_ID3D12Debug), (void **)&renderer->d3d12Debug);
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get ID3D12Debug interface");
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Debug_EnableDebugLayer(renderer->d3d12Debug);
|
ID3D12Debug_EnableDebugLayer(renderer->d3d12Debug);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
|
#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
|
||||||
static bool D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *renderer)
|
static void D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *renderer)
|
||||||
{
|
{
|
||||||
ID3D12InfoQueue *infoQueue = NULL;
|
ID3D12InfoQueue *infoQueue = NULL;
|
||||||
D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
|
D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
|
||||||
@@ -8404,7 +8516,7 @@ static bool D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *rende
|
|||||||
D3D_GUID(D3D_IID_ID3D12InfoQueue),
|
D3D_GUID(D3D_IID_ID3D12InfoQueue),
|
||||||
(void **)&infoQueue);
|
(void **)&infoQueue);
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
CHECK_D3D12_ERROR_AND_RETURN("Failed to convert ID3D12Device to ID3D12InfoQueue", false);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_zero(filter);
|
SDL_zero(filter);
|
||||||
@@ -8420,8 +8532,6 @@ static bool D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *rende
|
|||||||
true);
|
true);
|
||||||
|
|
||||||
ID3D12InfoQueue_Release(infoQueue);
|
ID3D12InfoQueue_Release(infoQueue);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WINAPI D3D12_INTERNAL_OnD3D12DebugInfoMsg(
|
static void WINAPI D3D12_INTERNAL_OnD3D12DebugInfoMsg(
|
||||||
@@ -8570,9 +8680,12 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
|||||||
|
|
||||||
#ifdef HAVE_IDXGIINFOQUEUE
|
#ifdef HAVE_IDXGIINFOQUEUE
|
||||||
// Initialize the DXGI debug layer, if applicable
|
// Initialize the DXGI debug layer, if applicable
|
||||||
|
bool hasDxgiDebug = false;
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
D3D12_INTERNAL_TryInitializeDXGIDebug(renderer);
|
hasDxgiDebug = D3D12_INTERNAL_TryInitializeDXGIDebug(renderer);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
bool hasDxgiDebug = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Load the CreateDXGIFactory1 function
|
// Load the CreateDXGIFactory1 function
|
||||||
@@ -8705,7 +8818,20 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
|||||||
|
|
||||||
// Initialize the D3D12 debug layer, if applicable
|
// Initialize the D3D12 debug layer, if applicable
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
D3D12_INTERNAL_TryInitializeD3D12Debug(renderer);
|
bool hasD3d12Debug = D3D12_INTERNAL_TryInitializeD3D12Debug(renderer);
|
||||||
|
if (hasDxgiDebug && hasD3d12Debug) {
|
||||||
|
SDL_LogInfo(
|
||||||
|
SDL_LOG_CATEGORY_GPU,
|
||||||
|
"Validation layers enabled, expect debug level performance!");
|
||||||
|
} else if (hasDxgiDebug || hasD3d12Debug) {
|
||||||
|
SDL_LogWarn(
|
||||||
|
SDL_LOG_CATEGORY_GPU,
|
||||||
|
"Validation layers partially enabled, some warnings may not be available");
|
||||||
|
} else {
|
||||||
|
SDL_LogWarn(
|
||||||
|
SDL_LOG_CATEGORY_GPU,
|
||||||
|
"Validation layers not found, continuing without validation");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the D3D12Device
|
// Create the D3D12Device
|
||||||
@@ -8752,9 +8878,7 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
|||||||
|
|
||||||
// Initialize the D3D12 debug info queue, if applicable
|
// Initialize the D3D12 debug info queue, if applicable
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
if (!D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(renderer)) {
|
D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(renderer);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
D3D12_INTERNAL_TryInitializeD3D12DebugInfoLogger(renderer);
|
D3D12_INTERNAL_TryInitializeD3D12DebugInfoLogger(renderer);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -840,6 +840,10 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
|
|||||||
dispatch_data_t data;
|
dispatch_data_t data;
|
||||||
id<MTLFunction> function;
|
id<MTLFunction> function;
|
||||||
|
|
||||||
|
if (!entrypoint) {
|
||||||
|
entrypoint = "main0";
|
||||||
|
}
|
||||||
|
|
||||||
if (format == SDL_GPU_SHADERFORMAT_MSL) {
|
if (format == SDL_GPU_SHADERFORMAT_MSL) {
|
||||||
NSString *codeString = [[NSString alloc]
|
NSString *codeString = [[NSString alloc]
|
||||||
initWithBytes:code
|
initWithBytes:code
|
||||||
@@ -1494,7 +1498,9 @@ static SDL_GPUTexture *METAL_CreateTexture(
|
|||||||
// Copy properties so we don't lose information when the client destroys them
|
// Copy properties so we don't lose information when the client destroys them
|
||||||
container->header.info = *createinfo;
|
container->header.info = *createinfo;
|
||||||
container->header.info.props = SDL_CreateProperties();
|
container->header.info.props = SDL_CreateProperties();
|
||||||
SDL_CopyProperties(createinfo->props, container->header.info.props);
|
if (createinfo->props) {
|
||||||
|
SDL_CopyProperties(createinfo->props, container->header.info.props);
|
||||||
|
}
|
||||||
|
|
||||||
container->activeTexture = texture;
|
container->activeTexture = texture;
|
||||||
container->textureCapacity = 1;
|
container->textureCapacity = 1;
|
||||||
|
|||||||
+130
-100
@@ -606,7 +606,7 @@ typedef struct VulkanSampler
|
|||||||
typedef struct VulkanShader
|
typedef struct VulkanShader
|
||||||
{
|
{
|
||||||
VkShaderModule shaderModule;
|
VkShaderModule shaderModule;
|
||||||
const char *entrypointName;
|
char *entrypointName;
|
||||||
SDL_GPUShaderStage stage;
|
SDL_GPUShaderStage stage;
|
||||||
Uint32 numSamplers;
|
Uint32 numSamplers;
|
||||||
Uint32 numStorageTextures;
|
Uint32 numStorageTextures;
|
||||||
@@ -1206,6 +1206,9 @@ struct VulkanRenderer
|
|||||||
SDL_Mutex *acquireUniformBufferLock;
|
SDL_Mutex *acquireUniformBufferLock;
|
||||||
SDL_Mutex *renderPassFetchLock;
|
SDL_Mutex *renderPassFetchLock;
|
||||||
SDL_Mutex *framebufferFetchLock;
|
SDL_Mutex *framebufferFetchLock;
|
||||||
|
SDL_Mutex *graphicsPipelineLayoutFetchLock;
|
||||||
|
SDL_Mutex *computePipelineLayoutFetchLock;
|
||||||
|
SDL_Mutex *descriptorSetLayoutFetchLock;
|
||||||
SDL_Mutex *windowLock;
|
SDL_Mutex *windowLock;
|
||||||
|
|
||||||
Uint8 defragInProgress;
|
Uint8 defragInProgress;
|
||||||
@@ -1223,7 +1226,7 @@ struct VulkanRenderer
|
|||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
|
|
||||||
static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer);
|
static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
|
||||||
static bool VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
|
static bool VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
|
||||||
static void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window);
|
static void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window);
|
||||||
static bool VULKAN_Wait(SDL_GPURenderer *driverData);
|
static bool VULKAN_Wait(SDL_GPURenderer *driverData);
|
||||||
@@ -1255,6 +1258,7 @@ static inline const char *VkErrorMessages(VkResult code)
|
|||||||
ERR_TO_STR(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
|
ERR_TO_STR(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
|
||||||
ERR_TO_STR(VK_SUBOPTIMAL_KHR)
|
ERR_TO_STR(VK_SUBOPTIMAL_KHR)
|
||||||
ERR_TO_STR(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)
|
ERR_TO_STR(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)
|
||||||
|
ERR_TO_STR(VK_ERROR_INVALID_SHADER_NV)
|
||||||
default:
|
default:
|
||||||
return "Unhandled VkResult!";
|
return "Unhandled VkResult!";
|
||||||
}
|
}
|
||||||
@@ -3175,7 +3179,7 @@ static void VULKAN_INTERNAL_DestroyShader(
|
|||||||
vulkanShader->shaderModule,
|
vulkanShader->shaderModule,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
SDL_free((void *)vulkanShader->entrypointName);
|
SDL_free(vulkanShader->entrypointName);
|
||||||
SDL_free(vulkanShader);
|
SDL_free(vulkanShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3750,10 +3754,13 @@ static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
|
|||||||
key.writeStorageBufferCount = writeStorageBufferCount;
|
key.writeStorageBufferCount = writeStorageBufferCount;
|
||||||
key.uniformBufferCount = uniformBufferCount;
|
key.uniformBufferCount = uniformBufferCount;
|
||||||
|
|
||||||
|
SDL_LockMutex(renderer->descriptorSetLayoutFetchLock);
|
||||||
|
|
||||||
if (SDL_FindInHashTable(
|
if (SDL_FindInHashTable(
|
||||||
renderer->descriptorSetLayoutHashTable,
|
renderer->descriptorSetLayoutHashTable,
|
||||||
(const void *)&key,
|
(const void *)&key,
|
||||||
(const void **)&layout)) {
|
(const void **)&layout)) {
|
||||||
|
SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3836,7 +3843,10 @@ static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
|
|||||||
NULL,
|
NULL,
|
||||||
&descriptorSetLayout);
|
&descriptorSetLayout);
|
||||||
|
|
||||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorSetLayout, NULL);
|
if (vulkanResult != VK_SUCCESS) {
|
||||||
|
SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
|
||||||
|
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorSetLayout, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
layout = SDL_malloc(sizeof(DescriptorSetLayout));
|
layout = SDL_malloc(sizeof(DescriptorSetLayout));
|
||||||
layout->descriptorSetLayout = descriptorSetLayout;
|
layout->descriptorSetLayout = descriptorSetLayout;
|
||||||
@@ -3858,6 +3868,7 @@ static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
|
|||||||
(const void *)allocedKey,
|
(const void *)allocedKey,
|
||||||
(const void *)layout, true);
|
(const void *)layout, true);
|
||||||
|
|
||||||
|
SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3878,10 +3889,14 @@ static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipeli
|
|||||||
key.fragmentStorageTextureCount = fragmentShader->numStorageTextures;
|
key.fragmentStorageTextureCount = fragmentShader->numStorageTextures;
|
||||||
key.fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
|
key.fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
|
||||||
key.fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
|
key.fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
|
||||||
|
|
||||||
|
SDL_LockMutex(renderer->graphicsPipelineLayoutFetchLock);
|
||||||
|
|
||||||
if (SDL_FindInHashTable(
|
if (SDL_FindInHashTable(
|
||||||
renderer->graphicsPipelineResourceLayoutHashTable,
|
renderer->graphicsPipelineResourceLayoutHashTable,
|
||||||
(const void *)&key,
|
(const void *)&key,
|
||||||
(const void **)&pipelineResourceLayout)) {
|
(const void **)&pipelineResourceLayout)) {
|
||||||
|
SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
|
||||||
return pipelineResourceLayout;
|
return pipelineResourceLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3964,6 +3979,7 @@ static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipeli
|
|||||||
|
|
||||||
if (vulkanResult != VK_SUCCESS) {
|
if (vulkanResult != VK_SUCCESS) {
|
||||||
VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, pipelineResourceLayout);
|
VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, pipelineResourceLayout);
|
||||||
|
SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
|
||||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
|
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3975,6 +3991,7 @@ static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipeli
|
|||||||
(const void *)allocedKey,
|
(const void *)allocedKey,
|
||||||
(const void *)pipelineResourceLayout, true);
|
(const void *)pipelineResourceLayout, true);
|
||||||
|
|
||||||
|
SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
|
||||||
return pipelineResourceLayout;
|
return pipelineResourceLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3993,10 +4010,13 @@ static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipeline
|
|||||||
key.readWriteStorageBufferCount = createinfo->num_readwrite_storage_buffers;
|
key.readWriteStorageBufferCount = createinfo->num_readwrite_storage_buffers;
|
||||||
key.uniformBufferCount = createinfo->num_uniform_buffers;
|
key.uniformBufferCount = createinfo->num_uniform_buffers;
|
||||||
|
|
||||||
|
SDL_LockMutex(renderer->computePipelineLayoutFetchLock);
|
||||||
|
|
||||||
if (SDL_FindInHashTable(
|
if (SDL_FindInHashTable(
|
||||||
renderer->computePipelineResourceLayoutHashTable,
|
renderer->computePipelineResourceLayoutHashTable,
|
||||||
(const void *)&key,
|
(const void *)&key,
|
||||||
(const void **)&pipelineResourceLayout)) {
|
(const void **)&pipelineResourceLayout)) {
|
||||||
|
SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
|
||||||
return pipelineResourceLayout;
|
return pipelineResourceLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4065,6 +4085,7 @@ static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipeline
|
|||||||
|
|
||||||
if (vulkanResult != VK_SUCCESS) {
|
if (vulkanResult != VK_SUCCESS) {
|
||||||
VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, pipelineResourceLayout);
|
VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, pipelineResourceLayout);
|
||||||
|
SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
|
||||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
|
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4076,6 +4097,7 @@ static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipeline
|
|||||||
(const void *)allocedKey,
|
(const void *)allocedKey,
|
||||||
(const void *)pipelineResourceLayout, true);
|
(const void *)pipelineResourceLayout, true);
|
||||||
|
|
||||||
|
SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
|
||||||
return pipelineResourceLayout;
|
return pipelineResourceLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4946,6 +4968,9 @@ static void VULKAN_DestroyDevice(
|
|||||||
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
|
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
|
||||||
SDL_DestroyMutex(renderer->renderPassFetchLock);
|
SDL_DestroyMutex(renderer->renderPassFetchLock);
|
||||||
SDL_DestroyMutex(renderer->framebufferFetchLock);
|
SDL_DestroyMutex(renderer->framebufferFetchLock);
|
||||||
|
SDL_DestroyMutex(renderer->graphicsPipelineLayoutFetchLock);
|
||||||
|
SDL_DestroyMutex(renderer->computePipelineLayoutFetchLock);
|
||||||
|
SDL_DestroyMutex(renderer->descriptorSetLayoutFetchLock);
|
||||||
SDL_DestroyMutex(renderer->windowLock);
|
SDL_DestroyMutex(renderer->windowLock);
|
||||||
|
|
||||||
renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
|
renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
|
||||||
@@ -5602,6 +5627,7 @@ static void VULKAN_PopDebugGroup(
|
|||||||
|
|
||||||
static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
|
static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
|
||||||
VulkanRenderer *renderer,
|
VulkanRenderer *renderer,
|
||||||
|
bool transitionToDefaultLayout,
|
||||||
const SDL_GPUTextureCreateInfo *createinfo)
|
const SDL_GPUTextureCreateInfo *createinfo)
|
||||||
{
|
{
|
||||||
VkResult vulkanResult;
|
VkResult vulkanResult;
|
||||||
@@ -5829,15 +5855,17 @@ static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
|
|||||||
&nameInfo);
|
&nameInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout.
|
if (transitionToDefaultLayout) {
|
||||||
VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
|
// Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout.
|
||||||
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
|
||||||
renderer,
|
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
||||||
barrierCommandBuffer,
|
renderer,
|
||||||
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
|
barrierCommandBuffer,
|
||||||
texture);
|
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
|
||||||
VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
|
texture);
|
||||||
VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer);
|
VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
|
||||||
|
VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
@@ -5887,6 +5915,7 @@ static void VULKAN_INTERNAL_CycleActiveBuffer(
|
|||||||
|
|
||||||
static void VULKAN_INTERNAL_CycleActiveTexture(
|
static void VULKAN_INTERNAL_CycleActiveTexture(
|
||||||
VulkanRenderer *renderer,
|
VulkanRenderer *renderer,
|
||||||
|
VulkanCommandBuffer *commandBuffer,
|
||||||
VulkanTextureContainer *container)
|
VulkanTextureContainer *container)
|
||||||
{
|
{
|
||||||
VulkanTexture *texture;
|
VulkanTexture *texture;
|
||||||
@@ -5904,8 +5933,15 @@ static void VULKAN_INTERNAL_CycleActiveTexture(
|
|||||||
// No texture is available, generate a new one.
|
// No texture is available, generate a new one.
|
||||||
texture = VULKAN_INTERNAL_CreateTexture(
|
texture = VULKAN_INTERNAL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
|
false,
|
||||||
&container->header.info);
|
&container->header.info);
|
||||||
|
|
||||||
|
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
||||||
|
renderer,
|
||||||
|
commandBuffer,
|
||||||
|
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
|
||||||
|
texture);
|
||||||
|
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5969,6 +6005,7 @@ static VulkanTextureSubresource *VULKAN_INTERNAL_PrepareTextureSubresourceForWri
|
|||||||
SDL_GetAtomicInt(&textureContainer->activeTexture->referenceCount) > 0) {
|
SDL_GetAtomicInt(&textureContainer->activeTexture->referenceCount) > 0) {
|
||||||
VULKAN_INTERNAL_CycleActiveTexture(
|
VULKAN_INTERNAL_CycleActiveTexture(
|
||||||
renderer,
|
renderer,
|
||||||
|
commandBuffer,
|
||||||
textureContainer);
|
textureContainer);
|
||||||
|
|
||||||
textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
|
textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
|
||||||
@@ -6682,7 +6719,6 @@ static SDL_GPUShader *VULKAN_CreateShader(
|
|||||||
VkResult vulkanResult;
|
VkResult vulkanResult;
|
||||||
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
|
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
|
||||||
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
||||||
size_t entryPointNameLength;
|
|
||||||
|
|
||||||
vulkanShader = SDL_malloc(sizeof(VulkanShader));
|
vulkanShader = SDL_malloc(sizeof(VulkanShader));
|
||||||
vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
@@ -6702,10 +6738,11 @@ static SDL_GPUShader *VULKAN_CreateShader(
|
|||||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateShaderModule, NULL);
|
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateShaderModule, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
entryPointNameLength = SDL_strlen(createinfo->entrypoint) + 1;
|
const char *entrypoint = createinfo->entrypoint;
|
||||||
vulkanShader->entrypointName = SDL_malloc(entryPointNameLength);
|
if (!entrypoint) {
|
||||||
SDL_utf8strlcpy((char *)vulkanShader->entrypointName, createinfo->entrypoint, entryPointNameLength);
|
entrypoint = "main";
|
||||||
|
}
|
||||||
|
vulkanShader->entrypointName = SDL_strdup(entrypoint);
|
||||||
vulkanShader->stage = createinfo->stage;
|
vulkanShader->stage = createinfo->stage;
|
||||||
vulkanShader->numSamplers = createinfo->num_samplers;
|
vulkanShader->numSamplers = createinfo->num_samplers;
|
||||||
vulkanShader->numStorageTextures = createinfo->num_storage_textures;
|
vulkanShader->numStorageTextures = createinfo->num_storage_textures;
|
||||||
@@ -6751,6 +6788,7 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
|
|||||||
|
|
||||||
texture = VULKAN_INTERNAL_CreateTexture(
|
texture = VULKAN_INTERNAL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
|
true,
|
||||||
createinfo);
|
createinfo);
|
||||||
|
|
||||||
if (texture == NULL) {
|
if (texture == NULL) {
|
||||||
@@ -6762,7 +6800,9 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
|
|||||||
// Copy properties so we don't lose information when the client destroys them
|
// Copy properties so we don't lose information when the client destroys them
|
||||||
container->header.info = *createinfo;
|
container->header.info = *createinfo;
|
||||||
container->header.info.props = SDL_CreateProperties();
|
container->header.info.props = SDL_CreateProperties();
|
||||||
SDL_CopyProperties(createinfo->props, container->header.info.props);
|
if (createinfo->props) {
|
||||||
|
SDL_CopyProperties(createinfo->props, container->header.info.props);
|
||||||
|
}
|
||||||
|
|
||||||
container->canBeCycled = true;
|
container->canBeCycled = true;
|
||||||
container->activeTexture = texture;
|
container->activeTexture = texture;
|
||||||
@@ -6925,7 +6965,7 @@ static void VULKAN_INTERNAL_ReleaseBuffer(
|
|||||||
renderer->buffersToDestroy[renderer->buffersToDestroyCount] = vulkanBuffer;
|
renderer->buffersToDestroy[renderer->buffersToDestroyCount] = vulkanBuffer;
|
||||||
renderer->buffersToDestroyCount += 1;
|
renderer->buffersToDestroyCount += 1;
|
||||||
|
|
||||||
vulkanBuffer->markedForDestroy = 1;
|
vulkanBuffer->markedForDestroy = true;
|
||||||
vulkanBuffer->container = NULL;
|
vulkanBuffer->container = NULL;
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->disposeLock);
|
SDL_UnlockMutex(renderer->disposeLock);
|
||||||
@@ -7943,11 +7983,11 @@ static void VULKAN_BindVertexBuffers(
|
|||||||
|
|
||||||
for (Uint32 i = 0; i < numBindings; i += 1) {
|
for (Uint32 i = 0; i < numBindings; i += 1) {
|
||||||
VulkanBuffer *buffer = ((VulkanBufferContainer *)bindings[i].buffer)->activeBuffer;
|
VulkanBuffer *buffer = ((VulkanBufferContainer *)bindings[i].buffer)->activeBuffer;
|
||||||
if (vulkanCommandBuffer->vertexBuffers[i] != buffer->buffer || vulkanCommandBuffer->vertexBufferOffsets[i] != bindings[i].offset) {
|
if (vulkanCommandBuffer->vertexBuffers[firstSlot + i] != buffer->buffer || vulkanCommandBuffer->vertexBufferOffsets[firstSlot + i] != bindings[i].offset) {
|
||||||
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, buffer);
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, buffer);
|
||||||
|
|
||||||
vulkanCommandBuffer->vertexBuffers[i] = buffer->buffer;
|
vulkanCommandBuffer->vertexBuffers[firstSlot + i] = buffer->buffer;
|
||||||
vulkanCommandBuffer->vertexBufferOffsets[i] = bindings[i].offset;
|
vulkanCommandBuffer->vertexBufferOffsets[firstSlot + i] = bindings[i].offset;
|
||||||
vulkanCommandBuffer->needVertexBufferBind = true;
|
vulkanCommandBuffer->needVertexBufferBind = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10445,7 +10485,9 @@ static bool VULKAN_Submit(
|
|||||||
Uint32 swapchainImageIndex;
|
Uint32 swapchainImageIndex;
|
||||||
VulkanTextureSubresource *swapchainTextureSubresource;
|
VulkanTextureSubresource *swapchainTextureSubresource;
|
||||||
VulkanMemorySubAllocator *allocator;
|
VulkanMemorySubAllocator *allocator;
|
||||||
bool presenting = false;
|
bool performCleanups =
|
||||||
|
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->presentDataCount > 0) ||
|
||||||
|
renderer->claimedWindowCount == 0;
|
||||||
|
|
||||||
SDL_LockMutex(renderer->submitLock);
|
SDL_LockMutex(renderer->submitLock);
|
||||||
|
|
||||||
@@ -10468,6 +10510,15 @@ static bool VULKAN_Submit(
|
|||||||
swapchainTextureSubresource);
|
swapchainTextureSubresource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (performCleanups &&
|
||||||
|
renderer->allocationsToDefragCount > 0 &&
|
||||||
|
!renderer->defragInProgress) {
|
||||||
|
if (!VULKAN_INTERNAL_DefragmentMemory(renderer, vulkanCommandBuffer))
|
||||||
|
{
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to defragment memory, likely OOM!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer)) {
|
if (!VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer)) {
|
||||||
SDL_UnlockMutex(renderer->submitLock);
|
SDL_UnlockMutex(renderer->submitLock);
|
||||||
return false;
|
return false;
|
||||||
@@ -10505,11 +10556,7 @@ static bool VULKAN_Submit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Present, if applicable
|
// Present, if applicable
|
||||||
bool result = true;
|
|
||||||
|
|
||||||
for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
|
for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
|
||||||
presenting = true;
|
|
||||||
|
|
||||||
presentData = &vulkanCommandBuffer->presentDatas[j];
|
presentData = &vulkanCommandBuffer->presentDatas[j];
|
||||||
|
|
||||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
@@ -10547,60 +10594,50 @@ static bool VULKAN_Submit(
|
|||||||
(presentData->windowData->frameCounter + 1) % renderer->allowedFramesInFlight;
|
(presentData->windowData->frameCounter + 1) % renderer->allowedFramesInFlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we can perform any cleanups
|
if (performCleanups) {
|
||||||
|
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
|
||||||
|
vulkanResult = renderer->vkGetFenceStatus(
|
||||||
|
renderer->logicalDevice,
|
||||||
|
renderer->submittedCommandBuffers[i]->inFlightFence->fence);
|
||||||
|
|
||||||
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
|
if (vulkanResult == VK_SUCCESS) {
|
||||||
vulkanResult = renderer->vkGetFenceStatus(
|
VULKAN_INTERNAL_CleanCommandBuffer(
|
||||||
renderer->logicalDevice,
|
renderer,
|
||||||
renderer->submittedCommandBuffers[i]->inFlightFence->fence);
|
renderer->submittedCommandBuffers[i],
|
||||||
|
false);
|
||||||
if (vulkanResult == VK_SUCCESS) {
|
|
||||||
VULKAN_INTERNAL_CleanCommandBuffer(
|
|
||||||
renderer,
|
|
||||||
renderer->submittedCommandBuffers[i],
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (renderer->checkEmptyAllocations) {
|
|
||||||
SDL_LockMutex(renderer->allocatorLock);
|
|
||||||
|
|
||||||
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
|
|
||||||
allocator = &renderer->memoryAllocator->subAllocators[i];
|
|
||||||
|
|
||||||
for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
|
|
||||||
if (allocator->allocations[j]->usedRegionCount == 0) {
|
|
||||||
VULKAN_INTERNAL_DeallocateMemory(
|
|
||||||
renderer,
|
|
||||||
allocator,
|
|
||||||
j);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->checkEmptyAllocations = false;
|
if (renderer->checkEmptyAllocations) {
|
||||||
|
SDL_LockMutex(renderer->allocatorLock);
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
|
||||||
}
|
allocator = &renderer->memoryAllocator->subAllocators[i];
|
||||||
|
|
||||||
// Check pending destroys
|
for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
|
||||||
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
|
if (allocator->allocations[j]->usedRegionCount == 0) {
|
||||||
|
VULKAN_INTERNAL_DeallocateMemory(
|
||||||
|
renderer,
|
||||||
|
allocator,
|
||||||
|
j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Defrag!
|
renderer->checkEmptyAllocations = false;
|
||||||
if (
|
|
||||||
presenting &&
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
renderer->allocationsToDefragCount > 0 &&
|
}
|
||||||
!renderer->defragInProgress) {
|
|
||||||
result = VULKAN_INTERNAL_DefragmentMemory(renderer);
|
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark command buffer as submitted
|
// Mark command buffer as submitted
|
||||||
// This must happen after defrag, because it will try to acquire new command buffers.
|
|
||||||
VULKAN_INTERNAL_ReleaseCommandBuffer(vulkanCommandBuffer);
|
VULKAN_INTERNAL_ReleaseCommandBuffer(vulkanCommandBuffer);
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->submitLock);
|
SDL_UnlockMutex(renderer->submitLock);
|
||||||
|
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool VULKAN_Cancel(
|
static bool VULKAN_Cancel(
|
||||||
@@ -10627,43 +10664,28 @@ static bool VULKAN_Cancel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool VULKAN_INTERNAL_DefragmentMemory(
|
static bool VULKAN_INTERNAL_DefragmentMemory(
|
||||||
VulkanRenderer *renderer)
|
VulkanRenderer *renderer,
|
||||||
|
VulkanCommandBuffer *commandBuffer)
|
||||||
{
|
{
|
||||||
VulkanMemoryAllocation *allocation;
|
|
||||||
VulkanMemoryUsedRegion *currentRegion;
|
|
||||||
VulkanBuffer *newBuffer;
|
|
||||||
VulkanTexture *newTexture;
|
|
||||||
VkBufferCopy bufferCopy;
|
|
||||||
VkImageCopy imageCopy;
|
|
||||||
VulkanCommandBuffer *commandBuffer;
|
|
||||||
VulkanTextureSubresource *srcSubresource;
|
|
||||||
VulkanTextureSubresource *dstSubresource;
|
|
||||||
Uint32 i, subresourceIndex;
|
|
||||||
|
|
||||||
renderer->defragInProgress = 1;
|
renderer->defragInProgress = 1;
|
||||||
|
|
||||||
commandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
|
|
||||||
if (commandBuffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
commandBuffer->isDefrag = 1;
|
commandBuffer->isDefrag = 1;
|
||||||
|
|
||||||
SDL_LockMutex(renderer->allocatorLock);
|
SDL_LockMutex(renderer->allocatorLock);
|
||||||
|
|
||||||
allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
|
VulkanMemoryAllocation *allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
|
||||||
renderer->allocationsToDefragCount -= 1;
|
renderer->allocationsToDefragCount -= 1;
|
||||||
|
|
||||||
/* For each used region in the allocation
|
/* For each used region in the allocation
|
||||||
* create a new resource, copy the data
|
* create a new resource, copy the data
|
||||||
* and re-point the resource containers
|
* and re-point the resource containers
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < allocation->usedRegionCount; i += 1) {
|
for (Uint32 i = 0; i < allocation->usedRegionCount; i += 1) {
|
||||||
currentRegion = allocation->usedRegions[i];
|
VulkanMemoryUsedRegion *currentRegion = allocation->usedRegions[i];
|
||||||
|
|
||||||
if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) {
|
if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) {
|
||||||
currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
||||||
newBuffer = VULKAN_INTERNAL_CreateBuffer(
|
VulkanBuffer *newBuffer = VULKAN_INTERNAL_CreateBuffer(
|
||||||
renderer,
|
renderer,
|
||||||
currentRegion->vulkanBuffer->size,
|
currentRegion->vulkanBuffer->size,
|
||||||
currentRegion->vulkanBuffer->usage,
|
currentRegion->vulkanBuffer->usage,
|
||||||
@@ -10673,6 +10695,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|||||||
|
|
||||||
if (newBuffer == NULL) {
|
if (newBuffer == NULL) {
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10691,6 +10714,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|||||||
VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
|
VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
|
||||||
newBuffer);
|
newBuffer);
|
||||||
|
|
||||||
|
VkBufferCopy bufferCopy;
|
||||||
bufferCopy.srcOffset = 0;
|
bufferCopy.srcOffset = 0;
|
||||||
bufferCopy.dstOffset = 0;
|
bufferCopy.dstOffset = 0;
|
||||||
bufferCopy.size = currentRegion->resourceSize;
|
bufferCopy.size = currentRegion->resourceSize;
|
||||||
@@ -10730,20 +10754,22 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|||||||
|
|
||||||
VULKAN_INTERNAL_ReleaseBuffer(renderer, currentRegion->vulkanBuffer);
|
VULKAN_INTERNAL_ReleaseBuffer(renderer, currentRegion->vulkanBuffer);
|
||||||
} else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
|
} else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
|
||||||
newTexture = VULKAN_INTERNAL_CreateTexture(
|
VulkanTexture *newTexture = VULKAN_INTERNAL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
|
false,
|
||||||
¤tRegion->vulkanTexture->container->header.info);
|
¤tRegion->vulkanTexture->container->header.info);
|
||||||
|
|
||||||
if (newTexture == NULL) {
|
if (newTexture == NULL) {
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GPUTextureCreateInfo info = currentRegion->vulkanTexture->container->header.info;
|
SDL_GPUTextureCreateInfo info = currentRegion->vulkanTexture->container->header.info;
|
||||||
for (subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
|
for (Uint32 subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
|
||||||
// copy subresource if necessary
|
// copy subresource if necessary
|
||||||
srcSubresource = ¤tRegion->vulkanTexture->subresources[subresourceIndex];
|
VulkanTextureSubresource *srcSubresource = ¤tRegion->vulkanTexture->subresources[subresourceIndex];
|
||||||
dstSubresource = &newTexture->subresources[subresourceIndex];
|
VulkanTextureSubresource *dstSubresource = &newTexture->subresources[subresourceIndex];
|
||||||
|
|
||||||
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
|
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
|
||||||
renderer,
|
renderer,
|
||||||
@@ -10751,12 +10777,14 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|||||||
VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
|
VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
|
||||||
srcSubresource);
|
srcSubresource);
|
||||||
|
|
||||||
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
|
VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
|
||||||
renderer,
|
renderer,
|
||||||
commandBuffer,
|
commandBuffer,
|
||||||
|
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
|
||||||
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
|
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
|
||||||
dstSubresource);
|
dstSubresource);
|
||||||
|
|
||||||
|
VkImageCopy imageCopy;
|
||||||
imageCopy.srcOffset.x = 0;
|
imageCopy.srcOffset.x = 0;
|
||||||
imageCopy.srcOffset.y = 0;
|
imageCopy.srcOffset.y = 0;
|
||||||
imageCopy.srcOffset.z = 0;
|
imageCopy.srcOffset.z = 0;
|
||||||
@@ -10808,8 +10836,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|||||||
|
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
|
|
||||||
return VULKAN_Submit(
|
return true;
|
||||||
(SDL_GPUCommandBuffer *)commandBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format Info
|
// Format Info
|
||||||
@@ -11673,6 +11700,9 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
renderer->acquireUniformBufferLock = SDL_CreateMutex();
|
renderer->acquireUniformBufferLock = SDL_CreateMutex();
|
||||||
renderer->renderPassFetchLock = SDL_CreateMutex();
|
renderer->renderPassFetchLock = SDL_CreateMutex();
|
||||||
renderer->framebufferFetchLock = SDL_CreateMutex();
|
renderer->framebufferFetchLock = SDL_CreateMutex();
|
||||||
|
renderer->graphicsPipelineLayoutFetchLock = SDL_CreateMutex();
|
||||||
|
renderer->computePipelineLayoutFetchLock = SDL_CreateMutex();
|
||||||
|
renderer->descriptorSetLayoutFetchLock = SDL_CreateMutex();
|
||||||
renderer->windowLock = SDL_CreateMutex();
|
renderer->windowLock = SDL_CreateMutex();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -11733,7 +11763,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
|
|
||||||
renderer->renderPassHashTable = SDL_CreateHashTable(
|
renderer->renderPassHashTable = SDL_CreateHashTable(
|
||||||
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
||||||
false, // manually synchronized due to timing
|
false, // manually synchronized due to lookup timing
|
||||||
VULKAN_INTERNAL_RenderPassHashFunction,
|
VULKAN_INTERNAL_RenderPassHashFunction,
|
||||||
VULKAN_INTERNAL_RenderPassHashKeyMatch,
|
VULKAN_INTERNAL_RenderPassHashKeyMatch,
|
||||||
VULKAN_INTERNAL_RenderPassHashDestroy,
|
VULKAN_INTERNAL_RenderPassHashDestroy,
|
||||||
@@ -11749,7 +11779,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
|
|
||||||
renderer->graphicsPipelineResourceLayoutHashTable = SDL_CreateHashTable(
|
renderer->graphicsPipelineResourceLayoutHashTable = SDL_CreateHashTable(
|
||||||
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
||||||
true, // thread-safe
|
false, // manually synchronized due to lookup timing
|
||||||
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction,
|
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction,
|
||||||
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch,
|
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch,
|
||||||
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashDestroy,
|
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashDestroy,
|
||||||
@@ -11757,7 +11787,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
|
|
||||||
renderer->computePipelineResourceLayoutHashTable = SDL_CreateHashTable(
|
renderer->computePipelineResourceLayoutHashTable = SDL_CreateHashTable(
|
||||||
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
||||||
true, // thread-safe
|
false, // manually synchronized due to lookup timing
|
||||||
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction,
|
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction,
|
||||||
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch,
|
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch,
|
||||||
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashDestroy,
|
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashDestroy,
|
||||||
@@ -11765,7 +11795,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
|
|
||||||
renderer->descriptorSetLayoutHashTable = SDL_CreateHashTable(
|
renderer->descriptorSetLayoutHashTable = SDL_CreateHashTable(
|
||||||
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
|
||||||
true, // thread-safe
|
false, // manually synchronized due to lookup timing
|
||||||
VULKAN_INTERNAL_DescriptorSetLayoutHashFunction,
|
VULKAN_INTERNAL_DescriptorSetLayoutHashFunction,
|
||||||
VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch,
|
VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch,
|
||||||
VULKAN_INTERNAL_DescriptorSetLayoutHashDestroy,
|
VULKAN_INTERNAL_DescriptorSetLayoutHashDestroy,
|
||||||
|
|||||||
@@ -62,6 +62,10 @@
|
|||||||
#define wcsstr SDL_wcsstr
|
#define wcsstr SDL_wcsstr
|
||||||
#define wcstol SDL_wcstol
|
#define wcstol SDL_wcstol
|
||||||
|
|
||||||
|
// These functions conflict when linking both SDL and hidapi statically
|
||||||
|
#define hid_winapi_descriptor_reconstruct_pp_data SDL_hid_winapi_descriptor_reconstruct_pp_data
|
||||||
|
#define hid_winapi_get_container_id SDL_hid_winapi_get_container_id
|
||||||
|
|
||||||
#undef HIDAPI_H__
|
#undef HIDAPI_H__
|
||||||
#include "windows/hid.c"
|
#include "windows/hid.c"
|
||||||
#define HAVE_PLATFORM_BACKEND 1
|
#define HAVE_PLATFORM_BACKEND 1
|
||||||
|
|||||||
@@ -1238,6 +1238,7 @@ static void init_xbox360(libusb_device_handle *device_handle, unsigned short idV
|
|||||||
(void)conf_desc;
|
(void)conf_desc;
|
||||||
|
|
||||||
if ((idVendor == 0x05ac && idProduct == 0x055b) /* Gamesir-G3w */ ||
|
if ((idVendor == 0x05ac && idProduct == 0x055b) /* Gamesir-G3w */ ||
|
||||||
|
(idVendor == 0x20d6 && idProduct == 0x4010) /* PowerA Battle Dragon Advanced Wireless Controller */ ||
|
||||||
idVendor == 0x0f0d /* Hori Xbox controllers */) {
|
idVendor == 0x0f0d /* Hori Xbox controllers */) {
|
||||||
unsigned char data[20];
|
unsigned char data[20];
|
||||||
|
|
||||||
|
|||||||
@@ -775,13 +775,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
|
|||||||
// All other gamepads have the standard set of 19 buttons and 6 axes
|
// All other gamepads have the standard set of 19 buttons and 6 axes
|
||||||
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string));
|
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string));
|
||||||
|
|
||||||
if (SDL_IsJoystickXboxSeriesX(vendor, product)) {
|
if (SDL_IsJoystickSteamController(vendor, product)) {
|
||||||
// XBox Series X Controllers have a share button under the guide button
|
|
||||||
SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string));
|
|
||||||
} else if (SDL_IsJoystickXboxOneElite(vendor, product)) {
|
|
||||||
// XBox One Elite Controllers have 4 back paddle buttons
|
|
||||||
SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,", sizeof(mapping_string));
|
|
||||||
} else if (SDL_IsJoystickSteamController(vendor, product)) {
|
|
||||||
// Steam controllers have 2 back paddle buttons
|
// Steam controllers have 2 back paddle buttons
|
||||||
SDL_strlcat(mapping_string, "paddle1:b12,paddle2:b11,", sizeof(mapping_string));
|
SDL_strlcat(mapping_string, "paddle1:b12,paddle2:b11,", sizeof(mapping_string));
|
||||||
} else if (SDL_IsJoystickNintendoSwitchPro(vendor, product) ||
|
} else if (SDL_IsJoystickNintendoSwitchPro(vendor, product) ||
|
||||||
@@ -822,6 +816,15 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
|
|||||||
SDL_strlcat(mapping_string, "paddle1:b16,paddle2:b15,paddle3:b14,paddle4:b13,", sizeof(mapping_string));
|
SDL_strlcat(mapping_string, "paddle1:b16,paddle2:b15,paddle3:b14,paddle4:b13,", sizeof(mapping_string));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SDL_GAMEPAD_TYPE_XBOXONE:
|
||||||
|
if (SDL_IsJoystickXboxOneElite(vendor, product)) {
|
||||||
|
// XBox One Elite Controllers have 4 back paddle buttons
|
||||||
|
SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,", sizeof(mapping_string));
|
||||||
|
} else if (SDL_IsJoystickXboxSeriesX(vendor, product)) {
|
||||||
|
// XBox Series X Controllers have a share button under the guide button
|
||||||
|
SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string));
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (vendor == 0 && product == 0) {
|
if (vendor == 0 && product == 0) {
|
||||||
// This is a Bluetooth Nintendo Switch Pro controller
|
// This is a Bluetooth Nintendo Switch Pro controller
|
||||||
|
|||||||
@@ -553,6 +553,7 @@ static const char *s_GamepadMappings[] = {
|
|||||||
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
|
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
|
||||||
"03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
"03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||||
"0500000049190000020400001b010000,GameSir T4 Pro,crc:8283,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b23,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
"0500000049190000020400001b010000,GameSir T4 Pro,crc:8283,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b23,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||||
|
"03000000373500009710000001020000,GameSir-K1 FLUX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||||
"03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
"03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||||
"03000000c01100000140000011010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
"03000000c01100000140000011010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||||
@@ -904,7 +905,7 @@ static const char *s_GamepadMappings[] = {
|
|||||||
"0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
|
"0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
|
||||||
#endif
|
#endif
|
||||||
#ifdef SDL_JOYSTICK_N3DS
|
#ifdef SDL_JOYSTICK_N3DS
|
||||||
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b0,b:b1,back:b2,dpdown:b7,dpleft:b5,dpright:b4,dpup:b6,leftshoulder:b9,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b15,rightx:a2,righty:a3,start:b3,x:b10,y:b11,",
|
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b1,b:b0,back:b2,dpdown:b7,dpleft:b5,dpright:b4,dpup:b6,leftshoulder:b9,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b15,rightx:a2,righty:a3,start:b3,x:b11,y:b10,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
#endif
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
@@ -277,6 +277,7 @@ static Uint32 initial_blacklist_devices[] = {
|
|||||||
MAKE_VIDPID(0x1532, 0x0282), // Razer Huntsman Mini Analog, non-functional DInput device
|
MAKE_VIDPID(0x1532, 0x0282), // Razer Huntsman Mini Analog, non-functional DInput device
|
||||||
MAKE_VIDPID(0x26ce, 0x01a2), // ASRock LED Controller
|
MAKE_VIDPID(0x26ce, 0x01a2), // ASRock LED Controller
|
||||||
MAKE_VIDPID(0x20d6, 0x0002), // PowerA Enhanced Wireless Controller for Nintendo Switch (charging port only)
|
MAKE_VIDPID(0x20d6, 0x0002), // PowerA Enhanced Wireless Controller for Nintendo Switch (charging port only)
|
||||||
|
MAKE_VIDPID(0x3434, 0x0211), // Keychron K1 Pro System Control
|
||||||
};
|
};
|
||||||
static SDL_vidpid_list blacklist_devices = {
|
static SDL_vidpid_list blacklist_devices = {
|
||||||
SDL_HINT_JOYSTICK_BLACKLIST_DEVICES, 0, 0, NULL,
|
SDL_HINT_JOYSTICK_BLACKLIST_DEVICES, 0, 0, NULL,
|
||||||
@@ -289,7 +290,17 @@ static Uint32 initial_flightstick_devices[] = {
|
|||||||
MAKE_VIDPID(0x044f, 0x0402), // HOTAS Warthog Joystick
|
MAKE_VIDPID(0x044f, 0x0402), // HOTAS Warthog Joystick
|
||||||
MAKE_VIDPID(0x044f, 0xb10a), // ThrustMaster, Inc. T.16000M Joystick
|
MAKE_VIDPID(0x044f, 0xb10a), // ThrustMaster, Inc. T.16000M Joystick
|
||||||
MAKE_VIDPID(0x046d, 0xc215), // Logitech Extreme 3D
|
MAKE_VIDPID(0x046d, 0xc215), // Logitech Extreme 3D
|
||||||
|
MAKE_VIDPID(0x0583, 0x6258), // Padix USB joystick with viewfinder
|
||||||
|
MAKE_VIDPID(0x0583, 0x688f), // Padix QF-688uv Windstorm Pro
|
||||||
|
MAKE_VIDPID(0x0583, 0x7070), // Padix QF-707u Bazooka
|
||||||
|
MAKE_VIDPID(0x0583, 0xa019), // Padix USB vibration joystick with viewfinder
|
||||||
|
MAKE_VIDPID(0x0583, 0xa131), // Padix USB Wireless 2.4GHz
|
||||||
|
MAKE_VIDPID(0x0583, 0xa209), // Padix MetalStrike ForceFeedback
|
||||||
|
MAKE_VIDPID(0x0583, 0xb010), // Padix MetalStrike Pro
|
||||||
|
MAKE_VIDPID(0x0583, 0xb012), // Padix Wireless MetalStrike
|
||||||
|
MAKE_VIDPID(0x0583, 0xb013), // Padix USB Wireless 2.4GHZ
|
||||||
MAKE_VIDPID(0x0738, 0x2221), // Saitek Pro Flight X-56 Rhino Stick
|
MAKE_VIDPID(0x0738, 0x2221), // Saitek Pro Flight X-56 Rhino Stick
|
||||||
|
MAKE_VIDPID(0x10f5, 0x7084), // Turtle Beach VelocityOne
|
||||||
MAKE_VIDPID(0x231d, 0x0126), // Gunfighter Mk.III 'Space Combat Edition' (right)
|
MAKE_VIDPID(0x231d, 0x0126), // Gunfighter Mk.III 'Space Combat Edition' (right)
|
||||||
MAKE_VIDPID(0x231d, 0x0127), // Gunfighter Mk.III 'Space Combat Edition' (left)
|
MAKE_VIDPID(0x231d, 0x0127), // Gunfighter Mk.III 'Space Combat Edition' (left)
|
||||||
MAKE_VIDPID(0x362c, 0x0001), // Yawman Arrow
|
MAKE_VIDPID(0x362c, 0x0001), // Yawman Arrow
|
||||||
@@ -331,6 +342,7 @@ static SDL_vidpid_list rog_gamepad_mice = {
|
|||||||
static Uint32 initial_throttle_devices[] = {
|
static Uint32 initial_throttle_devices[] = {
|
||||||
MAKE_VIDPID(0x044f, 0x0404), // HOTAS Warthog Throttle
|
MAKE_VIDPID(0x044f, 0x0404), // HOTAS Warthog Throttle
|
||||||
MAKE_VIDPID(0x0738, 0xa221), // Saitek Pro Flight X-56 Rhino Throttle
|
MAKE_VIDPID(0x0738, 0xa221), // Saitek Pro Flight X-56 Rhino Throttle
|
||||||
|
MAKE_VIDPID(0x10f5, 0x7085), // Turtle Beach VelocityOne Throttle
|
||||||
};
|
};
|
||||||
static SDL_vidpid_list throttle_devices = {
|
static SDL_vidpid_list throttle_devices = {
|
||||||
SDL_HINT_JOYSTICK_THROTTLE_DEVICES, 0, 0, NULL,
|
SDL_HINT_JOYSTICK_THROTTLE_DEVICES, 0, 0, NULL,
|
||||||
@@ -374,6 +386,14 @@ static Uint32 initial_wheel_devices[] = {
|
|||||||
MAKE_VIDPID(0x046d, 0xca03), // Logitech Momo Racing
|
MAKE_VIDPID(0x046d, 0xca03), // Logitech Momo Racing
|
||||||
MAKE_VIDPID(0x0483, 0x0522), // Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U)
|
MAKE_VIDPID(0x0483, 0x0522), // Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U)
|
||||||
MAKE_VIDPID(0x0483, 0xa355), // VRS DirectForce Pro Wheel Base
|
MAKE_VIDPID(0x0483, 0xa355), // VRS DirectForce Pro Wheel Base
|
||||||
|
MAKE_VIDPID(0x0583, 0xa132), // Padix USB Wireless 2.4GHz Wheelpad
|
||||||
|
MAKE_VIDPID(0x0583, 0xa133), // Padix USB Wireless 2.4GHz Wheel
|
||||||
|
MAKE_VIDPID(0x0583, 0xa202), // Padix Force Feedback Wheel
|
||||||
|
MAKE_VIDPID(0x0583, 0xb002), // Padix Vibration USB Wheel
|
||||||
|
MAKE_VIDPID(0x0583, 0xb005), // Padix USB Wheel
|
||||||
|
MAKE_VIDPID(0x0583, 0xb008), // Padix USB Wireless 2.4GHz Wheel
|
||||||
|
MAKE_VIDPID(0x0583, 0xb009), // Padix USB Wheel
|
||||||
|
MAKE_VIDPID(0x0583, 0xb018), // Padix TW6 Wheel
|
||||||
MAKE_VIDPID(0x0eb7, 0x0001), // Fanatec ClubSport Wheel Base V2
|
MAKE_VIDPID(0x0eb7, 0x0001), // Fanatec ClubSport Wheel Base V2
|
||||||
MAKE_VIDPID(0x0eb7, 0x0004), // Fanatec ClubSport Wheel Base V2.5
|
MAKE_VIDPID(0x0eb7, 0x0004), // Fanatec ClubSport Wheel Base V2.5
|
||||||
MAKE_VIDPID(0x0eb7, 0x0005), // Fanatec CSL Elite Wheel Base+ (PS4)
|
MAKE_VIDPID(0x0eb7, 0x0005), // Fanatec CSL Elite Wheel Base+ (PS4)
|
||||||
@@ -1814,6 +1834,14 @@ bool SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
|
|||||||
result = true;
|
result = true;
|
||||||
} else {
|
} else {
|
||||||
result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble);
|
result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble);
|
||||||
|
if (result) {
|
||||||
|
joystick->trigger_rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS;
|
||||||
|
if (joystick->trigger_rumble_resend == 0) {
|
||||||
|
joystick->trigger_rumble_resend = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
joystick->trigger_rumble_resend = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
@@ -1824,6 +1852,7 @@ bool SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
|
|||||||
joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
|
joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
|
||||||
} else {
|
} else {
|
||||||
joystick->trigger_rumble_expiration = 0;
|
joystick->trigger_rumble_expiration = 0;
|
||||||
|
joystick->trigger_rumble_resend = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2478,6 +2507,15 @@ void SDL_UpdateJoysticks(void)
|
|||||||
|
|
||||||
if (joystick->trigger_rumble_expiration && now >= joystick->trigger_rumble_expiration) {
|
if (joystick->trigger_rumble_expiration && now >= joystick->trigger_rumble_expiration) {
|
||||||
SDL_RumbleJoystickTriggers(joystick, 0, 0, 0);
|
SDL_RumbleJoystickTriggers(joystick, 0, 0, 0);
|
||||||
|
joystick->trigger_rumble_resend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joystick->trigger_rumble_resend && now >= joystick->trigger_rumble_resend) {
|
||||||
|
joystick->driver->RumbleTriggers(joystick, joystick->left_trigger_rumble, joystick->right_trigger_rumble);
|
||||||
|
joystick->trigger_rumble_resend = now + SDL_RUMBLE_RESEND_MS;
|
||||||
|
if (joystick->trigger_rumble_resend == 0) {
|
||||||
|
joystick->trigger_rumble_resend = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2858,7 +2896,8 @@ bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id)
|
|||||||
}
|
}
|
||||||
if (vendor_id == USB_VENDOR_HORI) {
|
if (vendor_id == USB_VENDOR_HORI) {
|
||||||
if (product_id == USB_PRODUCT_HORI_FIGHTING_COMMANDER_OCTA_SERIES_X ||
|
if (product_id == USB_PRODUCT_HORI_FIGHTING_COMMANDER_OCTA_SERIES_X ||
|
||||||
product_id == USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X) {
|
product_id == USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X ||
|
||||||
|
product_id == USB_PRODUCT_HORI_TAIKO_DRUM_CONTROLLER) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ struct SDL_Joystick
|
|||||||
Uint16 left_trigger_rumble _guarded;
|
Uint16 left_trigger_rumble _guarded;
|
||||||
Uint16 right_trigger_rumble _guarded;
|
Uint16 right_trigger_rumble _guarded;
|
||||||
Uint64 trigger_rumble_expiration _guarded;
|
Uint64 trigger_rumble_expiration _guarded;
|
||||||
|
Uint64 trigger_rumble_resend _guarded;
|
||||||
|
|
||||||
Uint8 led_red _guarded;
|
Uint8 led_red _guarded;
|
||||||
Uint8 led_green _guarded;
|
Uint8 led_green _guarded;
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
|
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
|
||||||
#define USB_PRODUCT_HORI_STEAM_CONTROLLER 0x01AB
|
#define USB_PRODUCT_HORI_STEAM_CONTROLLER 0x01AB
|
||||||
#define USB_PRODUCT_HORI_STEAM_CONTROLLER_BT 0x0196
|
#define USB_PRODUCT_HORI_STEAM_CONTROLLER_BT 0x0196
|
||||||
|
#define USB_PRODUCT_HORI_TAIKO_DRUM_CONTROLLER 0x01b2
|
||||||
#define USB_PRODUCT_LOGITECH_F310 0xc216
|
#define USB_PRODUCT_LOGITECH_F310 0xc216
|
||||||
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
|
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
|
||||||
#define USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK 0x2218
|
#define USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK 0x2218
|
||||||
|
|||||||
@@ -304,6 +304,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
|
|||||||
if (stderr_option == SDL_PROCESS_STDIO_INHERITED) {
|
if (stderr_option == SDL_PROCESS_STDIO_INHERITED) {
|
||||||
stderr_option = SDL_PROCESS_STDIO_NULL;
|
stderr_option = SDL_PROCESS_STDIO_NULL;
|
||||||
}
|
}
|
||||||
|
creation_flags |= CREATE_NO_WINDOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (stdin_option) {
|
switch (stdin_option) {
|
||||||
@@ -329,7 +330,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
|
|||||||
startup_info.hStdInput = stdin_pipe[READ_END];
|
startup_info.hStdInput = stdin_pipe[READ_END];
|
||||||
break;
|
break;
|
||||||
case SDL_PROCESS_STDIO_NULL:
|
case SDL_PROCESS_STDIO_NULL:
|
||||||
startup_info.hStdInput = CreateFile(TEXT("\\\\.\\NUL"), GENERIC_ALL, 0, &security_attributes, OPEN_EXISTING, 0, NULL);
|
startup_info.hStdInput = CreateFile(TEXT("\\\\.\\NUL"), (GENERIC_READ | GENERIC_WRITE), 0, &security_attributes, OPEN_EXISTING, 0, NULL);
|
||||||
break;
|
break;
|
||||||
case SDL_PROCESS_STDIO_INHERITED:
|
case SDL_PROCESS_STDIO_INHERITED:
|
||||||
default:
|
default:
|
||||||
@@ -366,7 +367,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
|
|||||||
startup_info.hStdOutput = stdout_pipe[WRITE_END];
|
startup_info.hStdOutput = stdout_pipe[WRITE_END];
|
||||||
break;
|
break;
|
||||||
case SDL_PROCESS_STDIO_NULL:
|
case SDL_PROCESS_STDIO_NULL:
|
||||||
startup_info.hStdOutput = CreateFile(TEXT("\\\\.\\NUL"), GENERIC_ALL, 0, &security_attributes, OPEN_EXISTING, 0, NULL);
|
startup_info.hStdOutput = CreateFile(TEXT("\\\\.\\NUL"), (GENERIC_READ | GENERIC_WRITE), 0, &security_attributes, OPEN_EXISTING, 0, NULL);
|
||||||
break;
|
break;
|
||||||
case SDL_PROCESS_STDIO_INHERITED:
|
case SDL_PROCESS_STDIO_INHERITED:
|
||||||
default:
|
default:
|
||||||
@@ -412,7 +413,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
|
|||||||
startup_info.hStdError = stderr_pipe[WRITE_END];
|
startup_info.hStdError = stderr_pipe[WRITE_END];
|
||||||
break;
|
break;
|
||||||
case SDL_PROCESS_STDIO_NULL:
|
case SDL_PROCESS_STDIO_NULL:
|
||||||
startup_info.hStdError = CreateFile(TEXT("\\\\.\\NUL"), GENERIC_ALL, 0, &security_attributes, OPEN_EXISTING, 0, NULL);
|
startup_info.hStdError = CreateFile(TEXT("\\\\.\\NUL"), (GENERIC_READ | GENERIC_WRITE), 0, &security_attributes, OPEN_EXISTING, 0, NULL);
|
||||||
break;
|
break;
|
||||||
case SDL_PROCESS_STDIO_INHERITED:
|
case SDL_PROCESS_STDIO_INHERITED:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1658,8 +1658,6 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
surface_colorspace = SDL_GetSurfaceColorspace(surface);
|
|
||||||
|
|
||||||
// Try to have the best pixel format for the texture
|
// Try to have the best pixel format for the texture
|
||||||
// No alpha, but a colorkey => promote to alpha
|
// No alpha, but a colorkey => promote to alpha
|
||||||
if (!SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
|
if (!SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
|
||||||
@@ -1721,6 +1719,9 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
surface_colorspace = SDL_GetSurfaceColorspace(surface);
|
||||||
|
texture_colorspace = surface_colorspace;
|
||||||
|
|
||||||
if (surface_colorspace == SDL_COLORSPACE_SRGB_LINEAR ||
|
if (surface_colorspace == SDL_COLORSPACE_SRGB_LINEAR ||
|
||||||
SDL_COLORSPACETRANSFER(surface_colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
SDL_COLORSPACETRANSFER(surface_colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
||||||
if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
||||||
@@ -3930,8 +3931,7 @@ bool SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_F
|
|||||||
real_srcrect.w = (float)texture->w;
|
real_srcrect.w = (float)texture->w;
|
||||||
real_srcrect.h = (float)texture->h;
|
real_srcrect.h = (float)texture->h;
|
||||||
if (srcrect) {
|
if (srcrect) {
|
||||||
if (!SDL_GetRectIntersectionFloat(srcrect, &real_srcrect, &real_srcrect) ||
|
if (!SDL_GetRectIntersectionFloat(srcrect, &real_srcrect, &real_srcrect)) {
|
||||||
real_srcrect.w == 0.0f || real_srcrect.h == 0.0f) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -445,7 +445,6 @@ static void GPU_InvalidateCachedState(SDL_Renderer *renderer)
|
|||||||
{
|
{
|
||||||
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
|
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
|
||||||
|
|
||||||
data->state.render_target = NULL;
|
|
||||||
data->state.scissor_enabled = false;
|
data->state.scissor_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ typedef enum
|
|||||||
static gulong (*g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
|
static gulong (*g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
|
||||||
static void (*g_object_unref)(gpointer object);
|
static void (*g_object_unref)(gpointer object);
|
||||||
static gchar *(*g_mkdtemp)(gchar *template);
|
static gchar *(*g_mkdtemp)(gchar *template);
|
||||||
gpointer (*g_object_ref_sink)(gpointer object);
|
static gpointer (*g_object_ref_sink)(gpointer object);
|
||||||
gpointer (*g_object_ref)(gpointer object);
|
static gpointer (*g_object_ref)(gpointer object);
|
||||||
|
|
||||||
// glib_typeof requires compiler-specific code and includes that are too complex
|
// glib_typeof requires compiler-specific code and includes that are too complex
|
||||||
// to be worth copy-pasting here
|
// to be worth copy-pasting here
|
||||||
|
|||||||
@@ -20,12 +20,13 @@
|
|||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
#include "SDL_internal.h"
|
#include "SDL_internal.h"
|
||||||
#include "SDL_blit.h"
|
|
||||||
|
|
||||||
#ifdef SDL_HAVE_BLIT_AUTO
|
#ifdef SDL_HAVE_BLIT_AUTO
|
||||||
|
|
||||||
/* *INDENT-OFF* */ // clang-format off
|
/* *INDENT-OFF* */ // clang-format off
|
||||||
|
|
||||||
|
#include "SDL_blit.h"
|
||||||
|
|
||||||
extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
|
extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
|
||||||
|
|
||||||
/* *INDENT-ON* */ // clang-format on
|
/* *INDENT-ON* */ // clang-format on
|
||||||
|
|||||||
@@ -1101,9 +1101,9 @@ bool SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surfac
|
|||||||
int dst_w, dst_h;
|
int dst_w, dst_h;
|
||||||
|
|
||||||
// Make sure the surfaces aren't locked
|
// Make sure the surfaces aren't locked
|
||||||
if (!SDL_SurfaceValid(src)) {
|
if (!SDL_SurfaceValid(src) || !src->pixels) {
|
||||||
return SDL_InvalidParamError("src");
|
return SDL_InvalidParamError("src");
|
||||||
} else if (!SDL_SurfaceValid(dst)) {
|
} else if (!SDL_SurfaceValid(dst) || !dst->pixels) {
|
||||||
return SDL_InvalidParamError("dst");
|
return SDL_InvalidParamError("dst");
|
||||||
} else if ((src->flags & SDL_SURFACE_LOCKED) || (dst->flags & SDL_SURFACE_LOCKED)) {
|
} else if ((src->flags & SDL_SURFACE_LOCKED) || (dst->flags & SDL_SURFACE_LOCKED)) {
|
||||||
return SDL_SetError("Surfaces must not be locked during blit");
|
return SDL_SetError("Surfaces must not be locked during blit");
|
||||||
@@ -1133,6 +1133,13 @@ bool SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surfac
|
|||||||
return SDL_BlitSurface(src, srcrect, dst, dstrect);
|
return SDL_BlitSurface(src, srcrect, dst, dstrect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src_w == 0) {
|
||||||
|
src_w = 1;
|
||||||
|
}
|
||||||
|
if (src_h == 0) {
|
||||||
|
src_h = 1;
|
||||||
|
}
|
||||||
|
|
||||||
scaling_w = (double)dst_w / src_w;
|
scaling_w = (double)dst_w / src_w;
|
||||||
scaling_h = (double)dst_h / src_h;
|
scaling_h = (double)dst_h / src_h;
|
||||||
|
|
||||||
|
|||||||
@@ -1731,12 +1731,25 @@ SDL_VideoDisplay *SDL_GetVideoDisplayForFullscreenWindow(SDL_Window *window)
|
|||||||
return SDL_GetVideoDisplay(displayID);
|
return SDL_GetVideoDisplay(displayID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SDL_PROP_SDL2_COMPAT_WINDOW_PREFERRED_FULLSCREEN_DISPLAY "sdl2-compat.window.preferred_fullscreen_display"
|
||||||
|
|
||||||
SDL_DisplayID SDL_GetDisplayForWindow(SDL_Window *window)
|
SDL_DisplayID SDL_GetDisplayForWindow(SDL_Window *window)
|
||||||
{
|
{
|
||||||
SDL_DisplayID displayID = 0;
|
SDL_DisplayID displayID = 0;
|
||||||
|
|
||||||
CHECK_WINDOW_MAGIC(window, 0);
|
CHECK_WINDOW_MAGIC(window, 0);
|
||||||
|
|
||||||
|
/* sdl2-compat calls this function to get a display on which to make the window fullscreen,
|
||||||
|
* so pass it the preferred fullscreen display ID in a property.
|
||||||
|
*/
|
||||||
|
SDL_PropertiesID window_props = SDL_GetWindowProperties(window);
|
||||||
|
SDL_VideoDisplay *fs_display = SDL_GetVideoDisplayForFullscreenWindow(window);
|
||||||
|
if (fs_display) {
|
||||||
|
SDL_SetNumberProperty(window_props, SDL_PROP_SDL2_COMPAT_WINDOW_PREFERRED_FULLSCREEN_DISPLAY, fs_display->id);
|
||||||
|
} else {
|
||||||
|
SDL_ClearProperty(window_props, SDL_PROP_SDL2_COMPAT_WINDOW_PREFERRED_FULLSCREEN_DISPLAY);
|
||||||
|
}
|
||||||
|
|
||||||
// An explicit fullscreen display overrides all
|
// An explicit fullscreen display overrides all
|
||||||
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
||||||
displayID = window->current_fullscreen_mode.displayID;
|
displayID = window->current_fullscreen_mode.displayID;
|
||||||
|
|||||||
@@ -2104,7 +2104,9 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL
|
|||||||
|
|
||||||
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||||
{
|
{
|
||||||
if (SDL_GetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH)) {
|
if (_sdlWindow->flags & SDL_WINDOW_POPUP_MENU) {
|
||||||
|
return YES;
|
||||||
|
} else if (SDL_GetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH)) {
|
||||||
return SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, false);
|
return SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, false);
|
||||||
} else {
|
} else {
|
||||||
return SDL_GetHintBoolean("SDL_MAC_MOUSE_FOCUS_CLICKTHROUGH", false);
|
return SDL_GetHintBoolean("SDL_MAC_MOUSE_FOCUS_CLICKTHROUGH", false);
|
||||||
@@ -2113,6 +2115,36 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
static void Cocoa_UpdateMouseFocus()
|
||||||
|
{
|
||||||
|
const NSPoint mouseLocation = [NSEvent mouseLocation];
|
||||||
|
|
||||||
|
// Find the topmost window under the pointer and send a motion event if it is an SDL window.
|
||||||
|
[NSApp enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
|
||||||
|
usingBlock:^(NSWindow *nswin, BOOL *stop) {
|
||||||
|
NSRect r = [nswin contentRectForFrameRect:[nswin frame]];
|
||||||
|
if (NSPointInRect(mouseLocation, r)) {
|
||||||
|
SDL_VideoDevice *vid = SDL_GetVideoDevice();
|
||||||
|
SDL_Window *sdlwindow;
|
||||||
|
for (sdlwindow = vid->windows; sdlwindow; sdlwindow = sdlwindow->next) {
|
||||||
|
if (nswin == ((__bridge SDL_CocoaWindowData *)sdlwindow->internal).nswindow) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*stop = YES;
|
||||||
|
if (sdlwindow) {
|
||||||
|
int wx, wy;
|
||||||
|
SDL_RelativeToGlobalForWindow(sdlwindow, sdlwindow->x, sdlwindow->y, &wx, &wy);
|
||||||
|
|
||||||
|
// Calculate the cursor coordinates relative to the window.
|
||||||
|
const float dx = mouseLocation.x - wx;
|
||||||
|
const float dy = (CGDisplayPixelsHigh(kCGDirectMainDisplay) - mouseLocation.y) - wy;
|
||||||
|
SDL_SendMouseMotion(0, sdlwindow, SDL_GLOBAL_MOUSE_ID, false, dx, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow *nswindow, NSView *nsview)
|
static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow *nswindow, NSView *nsview)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
@@ -2210,8 +2242,10 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
|
|||||||
} else {
|
} else {
|
||||||
if (window->flags & SDL_WINDOW_TOOLTIP) {
|
if (window->flags & SDL_WINDOW_TOOLTIP) {
|
||||||
[nswindow setIgnoresMouseEvents:YES];
|
[nswindow setIgnoresMouseEvents:YES];
|
||||||
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
[nswindow setAcceptsMouseMovedEvents:NO];
|
||||||
|
} else if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_HIDDEN)) {
|
||||||
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
|
Cocoa_UpdateMouseFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2531,8 +2565,8 @@ void Cocoa_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->internal;
|
SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->internal;
|
||||||
|
|
||||||
NSSize maxSize;
|
NSSize maxSize;
|
||||||
maxSize.width = window->max_w;
|
maxSize.width = window->max_w ? window->max_w : CGFLOAT_MAX;
|
||||||
maxSize.height = window->max_h;
|
maxSize.height = window->max_h ? window->max_h : CGFLOAT_MAX;
|
||||||
|
|
||||||
[windata.nswindow setContentMaxSize:maxSize];
|
[windata.nswindow setContentMaxSize:maxSize];
|
||||||
}
|
}
|
||||||
@@ -2596,6 +2630,9 @@ void Cocoa_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
[nswindow orderWindow:NSWindowBelow relativeTo:[[NSApp keyWindow] windowNumber]];
|
[nswindow orderWindow:NSWindowBelow relativeTo:[[NSApp keyWindow] windowNumber]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||||
|
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
|
Cocoa_UpdateMouseFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[nswindow setIsVisible:YES];
|
[nswindow setIsVisible:YES];
|
||||||
@@ -2643,6 +2680,7 @@ void Cocoa_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Cocoa_SetKeyboardFocus(new_focus, set_focus);
|
Cocoa_SetKeyboardFocus(new_focus, set_focus);
|
||||||
|
Cocoa_UpdateMouseFocus();
|
||||||
} else if (window->parent && waskey) {
|
} else if (window->parent && waskey) {
|
||||||
/* Key status is not automatically set on the parent when a child is hidden. Check if the
|
/* Key status is not automatically set on the parent when a child is hidden. Check if the
|
||||||
* child window was key, and set the first visible parent to be key if so.
|
* child window was key, and set the first visible parent to be key if so.
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ SDL_GLContext Emscripten_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *
|
|||||||
|
|
||||||
context = emscripten_webgl_create_context(window_data->canvas_id, &attribs);
|
context = emscripten_webgl_create_context(window_data->canvas_id, &attribs);
|
||||||
|
|
||||||
if (context < 0) {
|
if (!context) {
|
||||||
SDL_SetError("Could not create webgl context");
|
SDL_SetError("Could not create webgl context");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-2
@@ -112,7 +112,6 @@ sub open_file {
|
|||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
#include "SDL_internal.h"
|
#include "SDL_internal.h"
|
||||||
#include "SDL_surface_c.h"
|
|
||||||
|
|
||||||
#ifdef SDL_HAVE_BLIT_AUTO
|
#ifdef SDL_HAVE_BLIT_AUTO
|
||||||
|
|
||||||
@@ -641,6 +640,14 @@ sub output_copyinc
|
|||||||
__EOF__
|
__EOF__
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub output_copyinc_h
|
||||||
|
{
|
||||||
|
print FILE <<__EOF__;
|
||||||
|
#include "SDL_blit.h"
|
||||||
|
|
||||||
|
__EOF__
|
||||||
|
}
|
||||||
|
|
||||||
sub output_copyfunctable
|
sub output_copyfunctable
|
||||||
{
|
{
|
||||||
print FILE <<__EOF__;
|
print FILE <<__EOF__;
|
||||||
@@ -693,7 +700,7 @@ __EOF__
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
print FILE <<__EOF__;
|
print FILE <<__EOF__;
|
||||||
{ 0, 0, 0, 0, NULL }
|
{ SDL_PIXELFORMAT_UNKNOWN, SDL_PIXELFORMAT_UNKNOWN, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
__EOF__
|
__EOF__
|
||||||
@@ -716,6 +723,7 @@ sub output_copyfunc_c
|
|||||||
}
|
}
|
||||||
|
|
||||||
open_file("SDL_blit_auto.h");
|
open_file("SDL_blit_auto.h");
|
||||||
|
output_copyinc_h();
|
||||||
output_copydefs();
|
output_copydefs();
|
||||||
for (my $i = 0; $i <= $#src_formats; ++$i) {
|
for (my $i = 0; $i <= $#src_formats; ++$i) {
|
||||||
for (my $j = 0; $j <= $#dst_formats; ++$j) {
|
for (my $j = 0; $j <= $#dst_formats; ++$j) {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ RECENT REVISION HISTORY:
|
|||||||
Bug & warning fixes
|
Bug & warning fixes
|
||||||
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||||
Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
|
Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
|
||||||
Phil Jordan Dave Moore Roy Eltham
|
Phil Jordan Henner Zeller Dave Moore Roy Eltham
|
||||||
Hayaki Saito Nathan Reed Won Chun
|
Hayaki Saito Nathan Reed Won Chun
|
||||||
Luke Graham Johan Duparc Nick Verigakis the Horde3D community
|
Luke Graham Johan Duparc Nick Verigakis the Horde3D community
|
||||||
Thomas Ruf Ronny Chevalier github:rlyeh
|
Thomas Ruf Ronny Chevalier github:rlyeh
|
||||||
@@ -1914,6 +1914,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
|||||||
int i,j;
|
int i,j;
|
||||||
unsigned char *good;
|
unsigned char *good;
|
||||||
|
|
||||||
|
if (data == NULL) return data;
|
||||||
if (req_comp == img_n) return data;
|
if (req_comp == img_n) return data;
|
||||||
STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
|
STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
|
||||||
|
|
||||||
|
|||||||
@@ -124,31 +124,30 @@ static BOOL UIKit_ShowMessageBoxAlertController(const SDL_MessageBoxData *messag
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UIKit_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonID, int *result)
|
typedef struct UIKit_ShowMessageBoxData
|
||||||
|
{
|
||||||
|
const SDL_MessageBoxData *messageboxdata;
|
||||||
|
int *buttonID;
|
||||||
|
bool result;
|
||||||
|
} UIKit_ShowMessageBoxData;
|
||||||
|
|
||||||
|
static void SDLCALL UIKit_ShowMessageBoxMainThreadCallback(void *userdata)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if (UIKit_ShowMessageBoxAlertController(messageboxdata, buttonID)) {
|
UIKit_ShowMessageBoxData *data = (UIKit_ShowMessageBoxData *) userdata;
|
||||||
*result = true;
|
data->result = UIKit_ShowMessageBoxAlertController(data->messageboxdata, data->buttonID);
|
||||||
} else {
|
|
||||||
*result = SDL_SetError("Could not show message box.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID)
|
bool UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
UIKit_ShowMessageBoxData data = { messageboxdata, buttonID, false };
|
||||||
__block int result = true;
|
if (!SDL_RunOnMainThread(UIKit_ShowMessageBoxMainThreadCallback, &data, true)) {
|
||||||
|
return false;
|
||||||
if ([NSThread isMainThread]) {
|
} else if (!data.result) {
|
||||||
UIKit_ShowMessageBoxImpl(messageboxdata, buttonID, &result);
|
return SDL_SetError("Could not show message box.");
|
||||||
} else {
|
|
||||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
||||||
UIKit_ShowMessageBoxImpl(messageboxdata, buttonID, &result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SDL_VIDEO_DRIVER_UIKIT
|
#endif // SDL_VIDEO_DRIVER_UIKIT
|
||||||
@@ -240,7 +240,7 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
|
|||||||
int i;
|
int i;
|
||||||
SDL_MouseButtonFlags buttons = SDL_GetMouseState(NULL, NULL);
|
SDL_MouseButtonFlags buttons = SDL_GetMouseState(NULL, NULL);
|
||||||
|
|
||||||
for (i = 0; i < MAX_MOUSE_BUTTONS; ++i) {
|
for (i = 1; i <= MAX_MOUSE_BUTTONS; ++i) {
|
||||||
if (buttons & SDL_BUTTON_MASK(i)) {
|
if (buttons & SDL_BUTTON_MASK(i)) {
|
||||||
SDL_SendMouseButton(UIKit_GetEventTimestamp([touch timestamp]), sdlwindow, SDL_GLOBAL_MOUSE_ID, (Uint8)i, false);
|
SDL_SendMouseButton(UIKit_GetEventTimestamp([touch timestamp]), sdlwindow, SDL_GLOBAL_MOUSE_ID, (Uint8)i, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,16 +163,9 @@ static bool Wayland_SurfaceHasActiveTouches(struct wl_surface *surface)
|
|||||||
|
|
||||||
static Uint64 Wayland_GetEventTimestamp(Uint64 nsTimestamp)
|
static Uint64 Wayland_GetEventTimestamp(Uint64 nsTimestamp)
|
||||||
{
|
{
|
||||||
static Uint64 last;
|
static Uint64 timestamp_offset = 0;
|
||||||
static Uint64 timestamp_offset;
|
|
||||||
const Uint64 now = SDL_GetTicksNS();
|
const Uint64 now = SDL_GetTicksNS();
|
||||||
|
|
||||||
if (nsTimestamp < last) {
|
|
||||||
// 32-bit timer rollover, bump the offset
|
|
||||||
timestamp_offset += SDL_MS_TO_NS(0x100000000LLU);
|
|
||||||
}
|
|
||||||
last = nsTimestamp;
|
|
||||||
|
|
||||||
if (!timestamp_offset) {
|
if (!timestamp_offset) {
|
||||||
timestamp_offset = (now - nsTimestamp);
|
timestamp_offset = (now - nsTimestamp);
|
||||||
}
|
}
|
||||||
@@ -196,10 +189,25 @@ static const struct zwp_input_timestamps_v1_listener timestamp_listener = {
|
|||||||
Wayland_input_timestamp_listener
|
Wayland_input_timestamp_listener
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Uint64 Wayland_EventTimestampMSToNS(Uint32 wl_timestamp_ms)
|
||||||
|
{
|
||||||
|
static Uint64 timestamp_offset = 0;
|
||||||
|
static Uint32 last = 0;
|
||||||
|
|
||||||
|
// Handle 32-bit timer rollover.
|
||||||
|
if (wl_timestamp_ms < last) {
|
||||||
|
timestamp_offset += SDL_MS_TO_NS(SDL_UINT64_C(0x100000000));
|
||||||
|
}
|
||||||
|
last = wl_timestamp_ms;
|
||||||
|
wl_timestamp_ms += timestamp_offset;
|
||||||
|
|
||||||
|
return SDL_MS_TO_NS(wl_timestamp_ms) + timestamp_offset;
|
||||||
|
}
|
||||||
|
|
||||||
static Uint64 Wayland_GetKeyboardTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
static Uint64 Wayland_GetKeyboardTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
||||||
{
|
{
|
||||||
if (wl_timestamp_ms) {
|
if (wl_timestamp_ms) {
|
||||||
return Wayland_GetEventTimestamp(input->keyboard_timestamp_ns ? input->keyboard_timestamp_ns : SDL_MS_TO_NS(wl_timestamp_ms));
|
return Wayland_GetEventTimestamp(input->keyboard_timestamp_ns ? input->keyboard_timestamp_ns : Wayland_EventTimestampMSToNS(wl_timestamp_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -207,17 +215,13 @@ static Uint64 Wayland_GetKeyboardTimestamp(struct SDL_WaylandInput *input, Uint3
|
|||||||
|
|
||||||
static Uint64 Wayland_GetKeyboardTimestampRaw(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
static Uint64 Wayland_GetKeyboardTimestampRaw(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
||||||
{
|
{
|
||||||
if (wl_timestamp_ms) {
|
return input->keyboard_timestamp_ns ? input->keyboard_timestamp_ns : Wayland_EventTimestampMSToNS(wl_timestamp_ms);
|
||||||
return input->keyboard_timestamp_ns ? input->keyboard_timestamp_ns : SDL_MS_TO_NS(wl_timestamp_ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint64 Wayland_GetPointerTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
static Uint64 Wayland_GetPointerTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
||||||
{
|
{
|
||||||
if (wl_timestamp_ms) {
|
if (wl_timestamp_ms) {
|
||||||
return Wayland_GetEventTimestamp(input->pointer_timestamp_ns ? input->pointer_timestamp_ns : SDL_MS_TO_NS(wl_timestamp_ms));
|
return Wayland_GetEventTimestamp(input->pointer_timestamp_ns ? input->pointer_timestamp_ns : Wayland_EventTimestampMSToNS(wl_timestamp_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -226,7 +230,7 @@ static Uint64 Wayland_GetPointerTimestamp(struct SDL_WaylandInput *input, Uint32
|
|||||||
Uint64 Wayland_GetTouchTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
Uint64 Wayland_GetTouchTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms)
|
||||||
{
|
{
|
||||||
if (wl_timestamp_ms) {
|
if (wl_timestamp_ms) {
|
||||||
return Wayland_GetEventTimestamp(input->touch_timestamp_ns ? input->touch_timestamp_ns : SDL_MS_TO_NS(wl_timestamp_ms));
|
return Wayland_GetEventTimestamp(input->touch_timestamp_ns ? input->touch_timestamp_ns : Wayland_EventTimestampMSToNS(wl_timestamp_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -598,11 +602,11 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
|
|||||||
wind->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
wind->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
||||||
|
|
||||||
input->buttons_pressed = 0;
|
input->buttons_pressed = 0;
|
||||||
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_LEFT, false);
|
SDL_SendMouseButton(0, wind->sdlwindow, input->pointer_id, SDL_BUTTON_LEFT, false);
|
||||||
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_RIGHT, false);
|
SDL_SendMouseButton(0, wind->sdlwindow, input->pointer_id, SDL_BUTTON_RIGHT, false);
|
||||||
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_MIDDLE, false);
|
SDL_SendMouseButton(0, wind->sdlwindow, input->pointer_id, SDL_BUTTON_MIDDLE, false);
|
||||||
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_X1, false);
|
SDL_SendMouseButton(0, wind->sdlwindow, input->pointer_id, SDL_BUTTON_X1, false);
|
||||||
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_X2, false);
|
SDL_SendMouseButton(0, wind->sdlwindow, input->pointer_id, SDL_BUTTON_X2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A pointer leave event may be emitted if the compositor hides the pointer in response to receiving a touch event.
|
/* A pointer leave event may be emitted if the compositor hides the pointer in response to receiving a touch event.
|
||||||
@@ -1199,7 +1203,7 @@ static void touch_handler_motion(void *data, struct wl_touch *touch, uint32_t ti
|
|||||||
const float x = (float)wl_fixed_to_double(fx) / window_data->current.logical_width;
|
const float x = (float)wl_fixed_to_double(fx) / window_data->current.logical_width;
|
||||||
const float y = (float)wl_fixed_to_double(fy) / window_data->current.logical_height;
|
const float y = (float)wl_fixed_to_double(fy) / window_data->current.logical_height;
|
||||||
|
|
||||||
SDL_SendTouchMotion(Wayland_GetPointerTimestamp(input, timestamp), (SDL_TouchID)(uintptr_t)touch,
|
SDL_SendTouchMotion(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(uintptr_t)touch,
|
||||||
(SDL_FingerID)(id + 1), window_data->sdlwindow, x, y, 1.0f);
|
(SDL_FingerID)(id + 1), window_data->sdlwindow, x, y, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2951,7 +2955,7 @@ static void tablet_tool_handle_frame(void *data, struct zwp_tablet_tool_v2 *tool
|
|||||||
return; // Not a pen we report on.
|
return; // Not a pen we report on.
|
||||||
}
|
}
|
||||||
|
|
||||||
const Uint64 timestamp = Wayland_GetEventTimestamp(SDL_MS_TO_NS(time));
|
const Uint64 timestamp = Wayland_GetEventTimestamp(Wayland_EventTimestampMSToNS(time));
|
||||||
const SDL_PenID instance_id = sdltool->instance_id;
|
const SDL_PenID instance_id = sdltool->instance_id;
|
||||||
SDL_Window *window = sdltool->tool_focus;
|
SDL_Window *window = sdltool->tool_focus;
|
||||||
|
|
||||||
|
|||||||
@@ -2055,6 +2055,10 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
struct wl_callback *cb = wl_display_sync(_this->internal->display);
|
struct wl_callback *cb = wl_display_sync(_this->internal->display);
|
||||||
wl_callback_add_listener(cb, &show_hide_sync_listener, (void*)((uintptr_t)window->id));
|
wl_callback_add_listener(cb, &show_hide_sync_listener, (void*)((uintptr_t)window->id));
|
||||||
|
|
||||||
|
data->showing_window = true;
|
||||||
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0);
|
||||||
|
data->showing_window = false;
|
||||||
|
|
||||||
// Send an exposure event to signal that the client should draw.
|
// Send an exposure event to signal that the client should draw.
|
||||||
if (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME) {
|
if (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME) {
|
||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||||
@@ -2277,6 +2281,11 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win
|
|||||||
return SDL_FULLSCREEN_FAILED;
|
return SDL_FULLSCREEN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drop fullscreen leave requests when showing the window.
|
||||||
|
if (wind->showing_window && fullscreen == SDL_FULLSCREEN_OP_LEAVE) {
|
||||||
|
return SDL_FULLSCREEN_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
if (wind->show_hide_sync_required) {
|
if (wind->show_hide_sync_required) {
|
||||||
WAYLAND_wl_display_roundtrip(_this->internal->display);
|
WAYLAND_wl_display_roundtrip(_this->internal->display);
|
||||||
}
|
}
|
||||||
@@ -2331,6 +2340,11 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
{
|
{
|
||||||
SDL_WindowData *wind = window->internal;
|
SDL_WindowData *wind = window->internal;
|
||||||
|
|
||||||
|
// Drop restore requests when showing the window.
|
||||||
|
if (wind->showing_window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Not currently fullscreen or maximized, and no state pending; nothing to do.
|
// Not currently fullscreen or maximized, and no state pending; nothing to do.
|
||||||
if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED)) &&
|
if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED)) &&
|
||||||
!wind->fullscreen_deadline_count && !wind->maximized_restored_deadline_count) {
|
!wind->fullscreen_deadline_count && !wind->maximized_restored_deadline_count) {
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ struct SDL_WindowData
|
|||||||
bool is_fullscreen;
|
bool is_fullscreen;
|
||||||
bool fullscreen_exclusive;
|
bool fullscreen_exclusive;
|
||||||
bool drop_fullscreen_requests;
|
bool drop_fullscreen_requests;
|
||||||
|
bool showing_window;
|
||||||
bool fullscreen_was_positioned;
|
bool fullscreen_was_positioned;
|
||||||
bool show_hide_sync_required;
|
bool show_hide_sync_required;
|
||||||
bool scale_to_display;
|
bool scale_to_display;
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ static void WIN_UpdateMouseCapture(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus)
|
static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus, DWORD pos)
|
||||||
{
|
{
|
||||||
SDL_WindowData *data = window->internal;
|
SDL_WindowData *data = window->internal;
|
||||||
HWND hwnd = data->hwnd;
|
HWND hwnd = data->hwnd;
|
||||||
@@ -389,7 +389,8 @@ static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus)
|
|||||||
|
|
||||||
// In relative mode we are guaranteed to have mouse focus if we have keyboard focus
|
// In relative mode we are guaranteed to have mouse focus if we have keyboard focus
|
||||||
if (!SDL_GetMouse()->relative_mode) {
|
if (!SDL_GetMouse()->relative_mode) {
|
||||||
GetCursorPos(&cursorPos);
|
cursorPos.x = (LONG)GET_X_LPARAM(pos);
|
||||||
|
cursorPos.y = (LONG)GET_Y_LPARAM(pos);
|
||||||
ScreenToClient(hwnd, &cursorPos);
|
ScreenToClient(hwnd, &cursorPos);
|
||||||
SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)cursorPos.x, (float)cursorPos.y);
|
SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)cursorPos.x, (float)cursorPos.y);
|
||||||
}
|
}
|
||||||
@@ -472,11 +473,6 @@ static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource(ULONG extrainfo)
|
|||||||
return SDL_MOUSE_EVENT_SOURCE_PEN;
|
return SDL_MOUSE_EVENT_SOURCE_PEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Sometimes WM_INPUT events won't have the correct touch signature,
|
|
||||||
so we have to rely purely on the touch bit being set. */
|
|
||||||
if (SDL_TouchDevicesAvailable() && extrainfo & 0x80) {
|
|
||||||
return SDL_MOUSE_EVENT_SOURCE_TOUCH;
|
|
||||||
}
|
|
||||||
return SDL_MOUSE_EVENT_SOURCE_MOUSE;
|
return SDL_MOUSE_EVENT_SOURCE_MOUSE;
|
||||||
}
|
}
|
||||||
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
@@ -614,7 +610,8 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetMouseMessageSource(rawmouse->ulExtraInformation) != SDL_MOUSE_EVENT_SOURCE_MOUSE) {
|
if (GetMouseMessageSource(rawmouse->ulExtraInformation) != SDL_MOUSE_EVENT_SOURCE_MOUSE ||
|
||||||
|
(SDL_TouchDevicesAvailable() && (rawmouse->ulExtraInformation & 0x80) == 0x80)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1235,22 +1232,19 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
case WM_NCACTIVATE:
|
case WM_NCACTIVATE:
|
||||||
{
|
{
|
||||||
// Don't immediately clip the cursor in case we're clicking minimize/maximize buttons
|
// Don't immediately clip the cursor in case we're clicking minimize/maximize buttons
|
||||||
// This is the only place that this flag is set. This causes all subsequent calls to
|
data->postpone_clipcursor = true;
|
||||||
// WIN_UpdateClipCursor for this window to be no-ops in this frame's message-pumping.
|
data->clipcursor_queued = true;
|
||||||
// This flag is unset at the end of message pumping each frame for every window, and
|
|
||||||
// should never be carried over between frames.
|
|
||||||
data->skip_update_clipcursor = true;
|
|
||||||
|
|
||||||
/* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
|
/* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
|
||||||
actually being the foreground window, but this appears to get called in all cases where
|
actually being the foreground window, but this appears to get called in all cases where
|
||||||
the global foreground window changes to and from this window. */
|
the global foreground window changes to and from this window. */
|
||||||
WIN_UpdateFocus(data->window, !!wParam);
|
WIN_UpdateFocus(data->window, !!wParam, GetMessagePos());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_ACTIVATE:
|
case WM_ACTIVATE:
|
||||||
{
|
{
|
||||||
// Update the focus in case we changed focus to a child window and then away from the application
|
// Update the focus in case we changed focus to a child window and then away from the application
|
||||||
WIN_UpdateFocus(data->window, !!LOWORD(wParam));
|
WIN_UpdateFocus(data->window, !!LOWORD(wParam), GetMessagePos());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_MOUSEACTIVATE:
|
case WM_MOUSEACTIVATE:
|
||||||
@@ -1273,14 +1267,14 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
case WM_SETFOCUS:
|
case WM_SETFOCUS:
|
||||||
{
|
{
|
||||||
// Update the focus in case it's changing between top-level windows in the same application
|
// Update the focus in case it's changing between top-level windows in the same application
|
||||||
WIN_UpdateFocus(data->window, true);
|
WIN_UpdateFocus(data->window, true, GetMessagePos());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_KILLFOCUS:
|
case WM_KILLFOCUS:
|
||||||
case WM_ENTERIDLE:
|
case WM_ENTERIDLE:
|
||||||
{
|
{
|
||||||
// Update the focus in case it's changing between top-level windows in the same application
|
// Update the focus in case it's changing between top-level windows in the same application
|
||||||
WIN_UpdateFocus(data->window, false);
|
WIN_UpdateFocus(data->window, false, GetMessagePos());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_POINTERENTER:
|
case WM_POINTERENTER:
|
||||||
@@ -1361,8 +1355,10 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
const Uint64 timestamp = WIN_GetEventTimestamp();
|
const Uint64 timestamp = WIN_GetEventTimestamp();
|
||||||
SDL_Window *window = data->window;
|
SDL_Window *window = data->window;
|
||||||
|
|
||||||
|
const bool istouching = IS_POINTER_INCONTACT_WPARAM(wParam) && IS_POINTER_FIRSTBUTTON_WPARAM(wParam);
|
||||||
|
|
||||||
// if lifting off, do it first, so any motion changes don't cause app issues.
|
// if lifting off, do it first, so any motion changes don't cause app issues.
|
||||||
if (msg == WM_POINTERUP) {
|
if (!istouching) {
|
||||||
SDL_SendPenTouch(timestamp, pen, window, (pen_info.penFlags & PEN_FLAG_INVERTED) != 0, false);
|
SDL_SendPenTouch(timestamp, pen, window, (pen_info.penFlags & PEN_FLAG_INVERTED) != 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1392,7 +1388,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if setting down, do it last, so the pen is positioned correctly from the first contact.
|
// if setting down, do it last, so the pen is positioned correctly from the first contact.
|
||||||
if (msg == WM_POINTERDOWN) {
|
if (istouching) {
|
||||||
SDL_SendPenTouch(timestamp, pen, window, (pen_info.penFlags & PEN_FLAG_INVERTED) != 0, true);
|
SDL_SendPenTouch(timestamp, pen, window, (pen_info.penFlags & PEN_FLAG_INVERTED) != 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1408,9 +1404,8 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
window->flags & (SDL_WINDOW_MOUSE_RELATIVE_MODE | SDL_WINDOW_MOUSE_GRABBED) ||
|
window->flags & (SDL_WINDOW_MOUSE_RELATIVE_MODE | SDL_WINDOW_MOUSE_GRABBED) ||
|
||||||
(window->mouse_rect.w > 0 && window->mouse_rect.h > 0)
|
(window->mouse_rect.w > 0 && window->mouse_rect.h > 0)
|
||||||
);
|
);
|
||||||
if (wish_clip_cursor) {
|
if (wish_clip_cursor) { // queue clipcursor refresh on pump finish
|
||||||
data->skip_update_clipcursor = false;
|
data->clipcursor_queued = true;
|
||||||
WIN_UpdateClipCursor(window);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1435,6 +1430,9 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));
|
SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
@@ -1498,8 +1496,10 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
if (!(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
if (!(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||||
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !IsIconic(hwnd)) {
|
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !IsIconic(hwnd)) {
|
||||||
SDL_Mouse *mouse;
|
SDL_Mouse *mouse;
|
||||||
|
DWORD pos = GetMessagePos();
|
||||||
POINT cursorPos;
|
POINT cursorPos;
|
||||||
GetCursorPos(&cursorPos);
|
cursorPos.x = GET_X_LPARAM(pos);
|
||||||
|
cursorPos.y = GET_Y_LPARAM(pos);
|
||||||
ScreenToClient(hwnd, &cursorPos);
|
ScreenToClient(hwnd, &cursorPos);
|
||||||
mouse = SDL_GetMouse();
|
mouse = SDL_GetMouse();
|
||||||
if (!mouse->was_touch_mouse_events) { // we're not a touch handler causing a mouse leave?
|
if (!mouse->was_touch_mouse_events) { // we're not a touch handler causing a mouse leave?
|
||||||
@@ -1638,7 +1638,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
// Reference: https://gamedev.net/forums/topic/672094-keeping-things-moving-during-win32-moveresize-events/5254386/
|
// Reference: https://gamedev.net/forums/topic/672094-keeping-things-moving-during-win32-moveresize-events/5254386/
|
||||||
if (SendMessage(hwnd, WM_NCHITTEST, wParam, lParam) == HTCAPTION) {
|
if (SendMessage(hwnd, WM_NCHITTEST, wParam, lParam) == HTCAPTION) {
|
||||||
POINT cursorPos;
|
POINT cursorPos;
|
||||||
GetCursorPos(&cursorPos);
|
GetCursorPos(&cursorPos); // want the most current pos so as to not cause position change
|
||||||
ScreenToClient(hwnd, &cursorPos);
|
ScreenToClient(hwnd, &cursorPos);
|
||||||
PostMessage(hwnd, WM_MOUSEMOVE, 0, cursorPos.x | (((Uint32)((Sint16)cursorPos.y)) << 16));
|
PostMessage(hwnd, WM_MOUSEMOVE, 0, cursorPos.x | (((Uint32)((Sint16)cursorPos.y)) << 16));
|
||||||
}
|
}
|
||||||
@@ -1852,6 +1852,9 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
data->initial_size_rect.bottom = data->window->y + data->window->h;
|
data->initial_size_rect.bottom = data->window->y + data->window->h;
|
||||||
|
|
||||||
SetTimer(hwnd, (UINT_PTR)SDL_IterateMainCallbacks, USER_TIMER_MINIMUM, NULL);
|
SetTimer(hwnd, (UINT_PTR)SDL_IterateMainCallbacks, USER_TIMER_MINIMUM, NULL);
|
||||||
|
|
||||||
|
// Reset the keyboard, as we won't get any key up events during the modal loop
|
||||||
|
SDL_ResetKeyboard();
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -2590,13 +2593,27 @@ void WIN_PumpEvents(SDL_VideoDevice *_this)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the clipping rect in case someone else has stolen it
|
// fire queued clipcursor refreshes
|
||||||
if (_this) {
|
if (_this) {
|
||||||
SDL_Window *window = _this->windows;
|
SDL_Window *window = _this->windows;
|
||||||
while (window) {
|
while (window) {
|
||||||
|
bool refresh_clipcursor = false;
|
||||||
SDL_WindowData *data = window->internal;
|
SDL_WindowData *data = window->internal;
|
||||||
if (data && data->skip_update_clipcursor) {
|
if (data) {
|
||||||
data->skip_update_clipcursor = false;
|
refresh_clipcursor = data->clipcursor_queued;
|
||||||
|
data->clipcursor_queued = false; // Must be cleared unconditionally.
|
||||||
|
data->postpone_clipcursor = false; // Must be cleared unconditionally.
|
||||||
|
// Must happen before UpdateClipCursor.
|
||||||
|
// Although its occurrence currently
|
||||||
|
// always coincides with the queuing of
|
||||||
|
// clipcursor, it is logically distinct
|
||||||
|
// and this coincidence might no longer
|
||||||
|
// be true in the future.
|
||||||
|
// Ergo this placement concordantly
|
||||||
|
// conveys its unconditionality
|
||||||
|
// vis-a-vis the queuing of clipcursor.
|
||||||
|
}
|
||||||
|
if (refresh_clipcursor) {
|
||||||
WIN_UpdateClipCursor(window);
|
WIN_UpdateClipCursor(window);
|
||||||
}
|
}
|
||||||
window = window->next;
|
window = window->next;
|
||||||
|
|||||||
@@ -348,6 +348,10 @@ bool WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRec
|
|||||||
|
|
||||||
// Update any child windows
|
// Update any child windows
|
||||||
for (child_window = window->first_child; child_window; child_window = child_window->next_sibling) {
|
for (child_window = window->first_child; child_window; child_window = child_window->next_sibling) {
|
||||||
|
if (!child_window->internal) {
|
||||||
|
// This child window is not yet fully initialized.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!WIN_SetWindowPositionInternal(child_window, flags, SDL_WINDOWRECT_CURRENT)) {
|
if (!WIN_SetWindowPositionInternal(child_window, flags, SDL_WINDOWRECT_CURRENT)) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
@@ -1028,8 +1032,9 @@ void WIN_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *
|
|||||||
|
|
||||||
void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||||
{
|
{
|
||||||
|
SDL_WindowData *data = window->internal;
|
||||||
|
HWND hwnd = data->hwnd;
|
||||||
DWORD style;
|
DWORD style;
|
||||||
HWND hwnd;
|
|
||||||
|
|
||||||
bool bActivate = SDL_GetHintBoolean(SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN, true);
|
bool bActivate = SDL_GetHintBoolean(SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN, true);
|
||||||
|
|
||||||
@@ -1038,17 +1043,30 @@ void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
WIN_SetWindowPosition(_this, window);
|
WIN_SetWindowPosition(_this, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
hwnd = window->internal->hwnd;
|
// If the window isn't borderless and will be fullscreen, use the borderless style to hide the initial borders.
|
||||||
|
if (window->pending_flags & SDL_WINDOW_FULLSCREEN) {
|
||||||
|
if (!(window->flags & SDL_WINDOW_BORDERLESS)) {
|
||||||
|
window->flags |= SDL_WINDOW_BORDERLESS;
|
||||||
|
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
style &= ~STYLE_MASK;
|
||||||
|
style |= GetWindowStyle(window);
|
||||||
|
SetWindowLong(hwnd, GWL_STYLE, style);
|
||||||
|
window->flags &= ~SDL_WINDOW_BORDERLESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
style = GetWindowLong(hwnd, GWL_EXSTYLE);
|
style = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||||
if (style & WS_EX_NOACTIVATE) {
|
if (style & WS_EX_NOACTIVATE) {
|
||||||
bActivate = false;
|
bActivate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->showing_window = true;
|
||||||
if (bActivate) {
|
if (bActivate) {
|
||||||
ShowWindow(hwnd, SW_SHOW);
|
ShowWindow(hwnd, SW_SHOW);
|
||||||
} else {
|
} else {
|
||||||
// Use SetWindowPos instead of ShowWindow to avoid activating the parent window if this is a child window
|
// Use SetWindowPos instead of ShowWindow to avoid activating the parent window if this is a child window
|
||||||
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, window->internal->copybits_flag | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, window->internal->copybits_flag | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||||
}
|
}
|
||||||
|
data->showing_window = false;
|
||||||
|
|
||||||
if (window->flags & SDL_WINDOW_POPUP_MENU && bActivate) {
|
if (window->flags & SDL_WINDOW_POPUP_MENU && bActivate) {
|
||||||
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
@@ -1207,10 +1225,12 @@ void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
{
|
{
|
||||||
SDL_WindowData *data = window->internal;
|
SDL_WindowData *data = window->internal;
|
||||||
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
|
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||||
HWND hwnd = data->hwnd;
|
if (!data->showing_window || window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) {
|
||||||
data->expected_resize = true;
|
HWND hwnd = data->hwnd;
|
||||||
ShowWindow(hwnd, SW_RESTORE);
|
data->expected_resize = true;
|
||||||
data->expected_resize = false;
|
ShowWindow(hwnd, SW_RESTORE);
|
||||||
|
data->expected_resize = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
data->windowed_mode_was_maximized = false;
|
data->windowed_mode_was_maximized = false;
|
||||||
}
|
}
|
||||||
@@ -1218,18 +1238,22 @@ void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
|
|
||||||
static void WIN_UpdateCornerRoundingForHWND(SDL_VideoDevice *_this, HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
|
static void WIN_UpdateCornerRoundingForHWND(SDL_VideoDevice *_this, HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
|
||||||
{
|
{
|
||||||
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
SDL_VideoData *videodata = _this->internal;
|
SDL_VideoData *videodata = _this->internal;
|
||||||
if (videodata->DwmSetWindowAttribute) {
|
if (videodata->DwmSetWindowAttribute) {
|
||||||
videodata->DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
|
videodata->DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WIN_UpdateBorderColorForHWND(SDL_VideoDevice *_this, HWND hwnd, COLORREF colorRef)
|
static void WIN_UpdateBorderColorForHWND(SDL_VideoDevice *_this, HWND hwnd, COLORREF colorRef)
|
||||||
{
|
{
|
||||||
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
SDL_VideoData *videodata = _this->internal;
|
SDL_VideoData *videodata = _this->internal;
|
||||||
if (videodata->DwmSetWindowAttribute) {
|
if (videodata->DwmSetWindowAttribute) {
|
||||||
videodata->DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
|
videodata->DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1591,7 +1615,7 @@ void WIN_UnclipCursorForWindow(SDL_Window *window) {
|
|||||||
void WIN_UpdateClipCursor(SDL_Window *window)
|
void WIN_UpdateClipCursor(SDL_Window *window)
|
||||||
{
|
{
|
||||||
SDL_WindowData *data = window->internal;
|
SDL_WindowData *data = window->internal;
|
||||||
if (data->in_title_click || data->focus_click_pending || data->skip_update_clipcursor) {
|
if (data->in_title_click || data->focus_click_pending || data->postpone_clipcursor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,11 +78,13 @@ struct SDL_WindowData
|
|||||||
bool in_border_change;
|
bool in_border_change;
|
||||||
bool in_title_click;
|
bool in_title_click;
|
||||||
Uint8 focus_click_pending;
|
Uint8 focus_click_pending;
|
||||||
bool skip_update_clipcursor;
|
bool postpone_clipcursor;
|
||||||
|
bool clipcursor_queued;
|
||||||
bool windowed_mode_was_maximized;
|
bool windowed_mode_was_maximized;
|
||||||
bool in_window_deactivation;
|
bool in_window_deactivation;
|
||||||
bool force_ws_maximizebox;
|
bool force_ws_maximizebox;
|
||||||
bool disable_move_size_events;
|
bool disable_move_size_events;
|
||||||
|
bool showing_window;
|
||||||
int in_modal_loop;
|
int in_modal_loop;
|
||||||
RECT initial_size_rect;
|
RECT initial_size_rect;
|
||||||
RECT cursor_clipped_rect; // last successfully committed clipping rect for this window
|
RECT cursor_clipped_rect; // last successfully committed clipping rect for this window
|
||||||
|
|||||||
+128
-73
@@ -492,7 +492,17 @@ static void X11_DispatchFocusOut(SDL_VideoDevice *_this, SDL_WindowData *data)
|
|||||||
/* If another window has already processed a focus in, then don't try to
|
/* If another window has already processed a focus in, then don't try to
|
||||||
* remove focus here. Doing so will incorrectly remove focus from that
|
* remove focus here. Doing so will incorrectly remove focus from that
|
||||||
* window, and the focus lost event for this window will have already
|
* window, and the focus lost event for this window will have already
|
||||||
* been dispatched anyway. */
|
* been dispatched anyway.
|
||||||
|
*/
|
||||||
|
if (data->tracking_mouse_outside_window && data->window == SDL_GetMouseFocus()) {
|
||||||
|
// If tracking the pointer and keyboard focus is lost, raise all buttons and relinquish mouse focus.
|
||||||
|
SDL_SendMouseButton(0, data->window, SDL_GLOBAL_MOUSE_ID, SDL_BUTTON_LEFT, false);
|
||||||
|
SDL_SendMouseButton(0, data->window, SDL_GLOBAL_MOUSE_ID, SDL_BUTTON_MIDDLE, false);
|
||||||
|
SDL_SendMouseButton(0, data->window, SDL_GLOBAL_MOUSE_ID, SDL_BUTTON_RIGHT, false);
|
||||||
|
SDL_SendMouseButton(0, data->window, SDL_GLOBAL_MOUSE_ID, SDL_BUTTON_X1, false);
|
||||||
|
SDL_SendMouseButton(0, data->window, SDL_GLOBAL_MOUSE_ID, SDL_BUTTON_X2, false);
|
||||||
|
SDL_SetMouseFocus(NULL);
|
||||||
|
}
|
||||||
if (data->window == SDL_GetKeyboardFocus()) {
|
if (data->window == SDL_GetKeyboardFocus()) {
|
||||||
SDL_SetKeyboardFocus(NULL);
|
SDL_SetKeyboardFocus(NULL);
|
||||||
}
|
}
|
||||||
@@ -506,17 +516,32 @@ static void X11_DispatchFocusOut(SDL_VideoDevice *_this, SDL_WindowData *data)
|
|||||||
static void X11_DispatchMapNotify(SDL_WindowData *data)
|
static void X11_DispatchMapNotify(SDL_WindowData *data)
|
||||||
{
|
{
|
||||||
SDL_Window *window = data->window;
|
SDL_Window *window = data->window;
|
||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
|
||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0);
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0);
|
||||||
if (!(window->flags & SDL_WINDOW_HIDDEN) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
|
data->was_shown = true;
|
||||||
|
|
||||||
|
// This may be sent when restoring a minimized window.
|
||||||
|
if (window->flags & SDL_WINDOW_MINIMIZED) {
|
||||||
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
||||||
|
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
|
||||||
SDL_UpdateWindowGrab(window);
|
SDL_UpdateWindowGrab(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void X11_DispatchUnmapNotify(SDL_WindowData *data)
|
static void X11_DispatchUnmapNotify(SDL_WindowData *data)
|
||||||
{
|
{
|
||||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIDDEN, 0, 0);
|
SDL_Window *window = data->window;
|
||||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
|
||||||
|
// This may be sent when minimizing a window.
|
||||||
|
if (!window->is_hiding) {
|
||||||
|
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
||||||
|
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_OCCLUDED, 0, 0);
|
||||||
|
} else {
|
||||||
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIDDEN, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DispatchWindowMove(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point)
|
static void DispatchWindowMove(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point)
|
||||||
@@ -972,29 +997,26 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handled_by_ime) {
|
|
||||||
if (pressed) {
|
|
||||||
X11_HandleModifierKeys(videodata, scancode, true, true);
|
|
||||||
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, true);
|
|
||||||
|
|
||||||
if (*text && !(SDL_GetModState() & (SDL_KMOD_CTRL | SDL_KMOD_ALT))) {
|
|
||||||
text[text_length] = '\0';
|
|
||||||
X11_ClearComposition(windowdata);
|
|
||||||
SDL_SendKeyboardText(text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (X11_KeyRepeat(display, xevent)) {
|
|
||||||
// We're about to get a repeated key down, ignore the key up
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
X11_HandleModifierKeys(videodata, scancode, false, true);
|
|
||||||
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
|
X11_HandleModifierKeys(videodata, scancode, true, true);
|
||||||
|
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, true);
|
||||||
|
|
||||||
|
// Synthesize a text event if the IME didn't consume a printable character
|
||||||
|
if (*text && !(SDL_GetModState() & (SDL_KMOD_CTRL | SDL_KMOD_ALT))) {
|
||||||
|
text[text_length] = '\0';
|
||||||
|
X11_ClearComposition(windowdata);
|
||||||
|
SDL_SendKeyboardText(text);
|
||||||
|
}
|
||||||
|
|
||||||
X11_UpdateUserTime(windowdata, xevent->xkey.time);
|
X11_UpdateUserTime(windowdata, xevent->xkey.time);
|
||||||
|
} else {
|
||||||
|
if (X11_KeyRepeat(display, xevent)) {
|
||||||
|
// We're about to get a repeated key down, ignore the key up
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
X11_HandleModifierKeys(videodata, scancode, false, true);
|
||||||
|
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,6 +1084,16 @@ void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata,
|
|||||||
// see explanation at case ButtonPress
|
// see explanation at case ButtonPress
|
||||||
button -= (8 - SDL_BUTTON_X1);
|
button -= (8 - SDL_BUTTON_X1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the mouse is captured and all buttons are now released, clear the capture
|
||||||
|
* flag so the focus will be cleared if the mouse is outside the window.
|
||||||
|
*/
|
||||||
|
if ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) &&
|
||||||
|
!(SDL_GetMouseState(NULL, NULL) & ~SDL_BUTTON_MASK(button))) {
|
||||||
|
window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
||||||
|
windowdata->tracking_mouse_outside_window = false;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_SendMouseButton(timestamp, window, mouseID, button, false);
|
SDL_SendMouseButton(timestamp, window, mouseID, button, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1096,6 +1128,41 @@ void X11_GetBorderValues(SDL_WindowData *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X11_EmitConfigureNotifyEvents(SDL_WindowData *data, XConfigureEvent *xevent)
|
||||||
|
{
|
||||||
|
if (xevent->x != data->last_xconfigure.x ||
|
||||||
|
xevent->y != data->last_xconfigure.y) {
|
||||||
|
if (!data->size_move_event_flags) {
|
||||||
|
SDL_Window *w;
|
||||||
|
int x = xevent->x;
|
||||||
|
int y = xevent->y;
|
||||||
|
|
||||||
|
data->pending_operation &= ~X11_PENDING_OP_MOVE;
|
||||||
|
SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
|
||||||
|
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y);
|
||||||
|
|
||||||
|
for (w = data->window->first_child; w; w = w->next_sibling) {
|
||||||
|
// Don't update hidden child popup windows, their relative position doesn't change
|
||||||
|
if (SDL_WINDOW_IS_POPUP(w) && !(w->flags & SDL_WINDOW_HIDDEN)) {
|
||||||
|
X11_UpdateWindowPosition(w, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xevent->width != data->last_xconfigure.width ||
|
||||||
|
xevent->height != data->last_xconfigure.height) {
|
||||||
|
if (!data->size_move_event_flags) {
|
||||||
|
data->pending_operation &= ~X11_PENDING_OP_RESIZE;
|
||||||
|
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED,
|
||||||
|
xevent->width,
|
||||||
|
xevent->height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_copyp(&data->last_xconfigure, xevent);
|
||||||
|
}
|
||||||
|
|
||||||
static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||||
{
|
{
|
||||||
SDL_VideoData *videodata = _this->internal;
|
SDL_VideoData *videodata = _this->internal;
|
||||||
@@ -1272,6 +1339,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
|||||||
SDL_Log("Mode: NotifyUngrab");
|
SDL_Log("Mode: NotifyUngrab");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
data->tracking_mouse_outside_window = false;
|
||||||
|
|
||||||
SDL_SetMouseFocus(data->window);
|
SDL_SetMouseFocus(data->window);
|
||||||
|
|
||||||
mouse->last_x = xevent->xcrossing.x;
|
mouse->last_x = xevent->xcrossing.x;
|
||||||
@@ -1318,14 +1387,17 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
|||||||
if (xevent->xcrossing.mode != NotifyGrab &&
|
if (xevent->xcrossing.mode != NotifyGrab &&
|
||||||
xevent->xcrossing.mode != NotifyUngrab &&
|
xevent->xcrossing.mode != NotifyUngrab &&
|
||||||
xevent->xcrossing.detail != NotifyInferior) {
|
xevent->xcrossing.detail != NotifyInferior) {
|
||||||
|
if (!(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||||
|
/* In order for interaction with the window decorations and menu to work properly
|
||||||
|
on Mutter, we need to ungrab the keyboard when the mouse leaves. */
|
||||||
|
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||||
|
X11_SetWindowKeyboardGrab(_this, data->window, false);
|
||||||
|
}
|
||||||
|
|
||||||
/* In order for interaction with the window decorations and menu to work properly
|
SDL_SetMouseFocus(NULL);
|
||||||
on Mutter, we need to ungrab the keyboard when the the mouse leaves. */
|
} else {
|
||||||
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN)) {
|
data->tracking_mouse_outside_window = true;
|
||||||
X11_SetWindowKeyboardGrab(_this, data->window, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetMouseFocus(NULL);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -1447,9 +1519,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
|||||||
xevent->xconfigure.x, xevent->xconfigure.y,
|
xevent->xconfigure.x, xevent->xconfigure.y,
|
||||||
xevent->xconfigure.width, xevent->xconfigure.height);
|
xevent->xconfigure.width, xevent->xconfigure.height);
|
||||||
#endif
|
#endif
|
||||||
// Real configure notify events are relative to the parent, synthetic events are absolute.
|
// Real configure notify events are relative to the parent, synthetic events are absolute.
|
||||||
if (!xevent->xconfigure.send_event)
|
if (!xevent->xconfigure.send_event) {
|
||||||
{
|
|
||||||
unsigned int NumChildren;
|
unsigned int NumChildren;
|
||||||
Window ChildReturn, Root, Parent;
|
Window ChildReturn, Root, Parent;
|
||||||
Window *Children;
|
Window *Children;
|
||||||
@@ -1462,41 +1533,23 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
|||||||
&ChildReturn);
|
&ChildReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xevent->xconfigure.x != data->last_xconfigure.x ||
|
/* Xfce sends ConfigureNotify before PropertyNotify when toggling fullscreen and maximized, which
|
||||||
xevent->xconfigure.y != data->last_xconfigure.y) {
|
* is backwards from every other window manager, as well as what is expected by SDL and its clients.
|
||||||
if (!data->size_move_event_flags) {
|
* Defer emitting the size/move events until the corresponding PropertyNotify arrives.
|
||||||
SDL_Window *w;
|
*/
|
||||||
int x = xevent->xconfigure.x;
|
const Uint32 changed = X11_GetNetWMState(_this, data->window, xevent->xproperty.window) ^ data->window->flags;
|
||||||
int y = xevent->xconfigure.y;
|
if (changed & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED)) {
|
||||||
|
SDL_copyp(&data->pending_xconfigure, &xevent->xconfigure);
|
||||||
|
data->emit_size_move_after_property_notify = true;
|
||||||
|
}
|
||||||
|
|
||||||
data->pending_operation &= ~X11_PENDING_OP_MOVE;
|
if (!data->emit_size_move_after_property_notify) {
|
||||||
SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
|
X11_EmitConfigureNotifyEvents(data, &xevent->xconfigure);
|
||||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y);
|
|
||||||
|
|
||||||
for (w = data->window->first_child; w; w = w->next_sibling) {
|
|
||||||
// Don't update hidden child popup windows, their relative position doesn't change
|
|
||||||
if (SDL_WINDOW_IS_POPUP(w) && !(w->flags & SDL_WINDOW_HIDDEN)) {
|
|
||||||
X11_UpdateWindowPosition(w, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
|
#ifdef SDL_VIDEO_DRIVER_X11_XSYNC
|
||||||
X11_HandleConfigure(data->window, &xevent->xconfigure);
|
X11_HandleConfigure(data->window, &xevent->xconfigure);
|
||||||
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */
|
#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */
|
||||||
|
|
||||||
if (xevent->xconfigure.width != data->last_xconfigure.width ||
|
|
||||||
xevent->xconfigure.height != data->last_xconfigure.height) {
|
|
||||||
if (!data->size_move_event_flags) {
|
|
||||||
data->pending_operation &= ~X11_PENDING_OP_RESIZE;
|
|
||||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED,
|
|
||||||
xevent->xconfigure.width,
|
|
||||||
xevent->xconfigure.height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data->last_xconfigure = xevent->xconfigure;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// Have we been requested to quit (or another client message?)
|
// Have we been requested to quit (or another client message?)
|
||||||
@@ -1782,19 +1835,15 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
|||||||
|
|
||||||
if (xevent->xproperty.atom == data->videodata->atoms._NET_WM_STATE) {
|
if (xevent->xproperty.atom == data->videodata->atoms._NET_WM_STATE) {
|
||||||
/* Get the new state from the window manager.
|
/* Get the new state from the window manager.
|
||||||
Compositing window managers can alter visibility of windows
|
* Compositing window managers can alter visibility of windows
|
||||||
without ever mapping / unmapping them, so we handle that here,
|
* without ever mapping / unmapping them, so we handle that here,
|
||||||
because they use the NETWM protocol to notify us of changes.
|
* because they use the NETWM protocol to notify us of changes.
|
||||||
*/
|
*/
|
||||||
const SDL_WindowFlags flags = X11_GetNetWMState(_this, data->window, xevent->xproperty.window);
|
const SDL_WindowFlags flags = X11_GetNetWMState(_this, data->window, xevent->xproperty.window);
|
||||||
const SDL_WindowFlags changed = flags ^ data->window->flags;
|
const SDL_WindowFlags changed = flags ^ data->window->flags;
|
||||||
|
|
||||||
if ((changed & (SDL_WINDOW_HIDDEN | SDL_WINDOW_FULLSCREEN)) != 0) {
|
if ((changed & SDL_WINDOW_HIDDEN) && !(flags & SDL_WINDOW_HIDDEN)) {
|
||||||
if (flags & SDL_WINDOW_HIDDEN) {
|
X11_DispatchMapNotify(data);
|
||||||
X11_DispatchUnmapNotify(data);
|
|
||||||
} else {
|
|
||||||
X11_DispatchMapNotify(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_WINDOW_IS_POPUP(data->window)) {
|
if (!SDL_WINDOW_IS_POPUP(data->window)) {
|
||||||
@@ -1805,6 +1854,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
|||||||
if (!(flags & SDL_WINDOW_MINIMIZED)) {
|
if (!(flags & SDL_WINDOW_MINIMIZED)) {
|
||||||
const bool commit = SDL_memcmp(&data->window->current_fullscreen_mode, &data->requested_fullscreen_mode, sizeof(SDL_DisplayMode)) != 0;
|
const bool commit = SDL_memcmp(&data->window->current_fullscreen_mode, &data->requested_fullscreen_mode, sizeof(SDL_DisplayMode)) != 0;
|
||||||
|
|
||||||
|
// Ensure the maximized flag is cleared before entering fullscreen.
|
||||||
|
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
||||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0);
|
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0);
|
||||||
if (commit) {
|
if (commit) {
|
||||||
/* This was initiated by the compositor, or the mode was changed between the request and the window
|
/* This was initiated by the compositor, or the mode was changed between the request and the window
|
||||||
@@ -1896,6 +1947,10 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (data->emit_size_move_after_property_notify) {
|
||||||
|
X11_EmitConfigureNotifyEvents(data, &data->pending_xconfigure);
|
||||||
|
data->emit_size_move_after_property_notify = false;
|
||||||
|
}
|
||||||
if ((flags & SDL_WINDOW_INPUT_FOCUS)) {
|
if ((flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||||
if (data->pending_move) {
|
if (data->pending_move) {
|
||||||
DispatchWindowMove(_this, data, &data->pending_move_point);
|
DispatchWindowMove(_this, data, &data->pending_move_point);
|
||||||
|
|||||||
@@ -425,6 +425,11 @@ static bool X11_MessageBoxCreateWindow(SDL_MessageBoxDataX11 *data)
|
|||||||
Display *display = data->display;
|
Display *display = data->display;
|
||||||
SDL_WindowData *windowdata = NULL;
|
SDL_WindowData *windowdata = NULL;
|
||||||
const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
|
const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
|
||||||
|
#ifdef XRANDR_DISABLED_BY_DEFAULT
|
||||||
|
const bool use_xrandr_by_default = false;
|
||||||
|
#else
|
||||||
|
const bool use_xrandr_by_default = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (messageboxdata->window) {
|
if (messageboxdata->window) {
|
||||||
SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(messageboxdata->window);
|
SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(messageboxdata->window);
|
||||||
@@ -497,7 +502,13 @@ static bool X11_MessageBoxCreateWindow(SDL_MessageBoxDataX11 *data)
|
|||||||
const SDL_DisplayData *dpydata = dpy->internal;
|
const SDL_DisplayData *dpydata = dpy->internal;
|
||||||
x = dpydata->x + ((dpy->current_mode->w - data->dialog_width) / 2);
|
x = dpydata->x + ((dpy->current_mode->w - data->dialog_width) / 2);
|
||||||
y = dpydata->y + ((dpy->current_mode->h - data->dialog_height) / 3);
|
y = dpydata->y + ((dpy->current_mode->h - data->dialog_height) / 3);
|
||||||
} else { // oh well. This will misposition on a multi-head setup. Init first next time.
|
} else if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XRANDR, use_xrandr_by_default)) {
|
||||||
|
XRRScreenResources *screen = X11_XRRGetScreenResourcesCurrent(display, DefaultRootWindow(display));
|
||||||
|
XRRCrtcInfo *crtc_info = X11_XRRGetCrtcInfo(display, screen, screen->crtcs[0]);
|
||||||
|
x = (crtc_info->width - data->dialog_width) / 2;
|
||||||
|
y = (crtc_info->height - data->dialog_height) / 3;
|
||||||
|
} else {
|
||||||
|
// oh well. This will misposition on a multi-head setup. Init first next time.
|
||||||
x = (DisplayWidth(display, data->screen) - data->dialog_width) / 2;
|
x = (DisplayWidth(display, data->screen) - data->dialog_width) / 2;
|
||||||
y = (DisplayHeight(display, data->screen) - data->dialog_height) / 3;
|
y = (DisplayHeight(display, data->screen) - data->dialog_height) / 3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -534,7 +534,7 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, false);
|
const bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, false);
|
||||||
const bool use_resize_sync = !(window->flags & SDL_WINDOW_VULKAN); /* doesn't work well with Vulkan */
|
const bool use_resize_sync = !!(window->flags & SDL_WINDOW_OPENGL); // Doesn't work well with Vulkan
|
||||||
SDL_WindowData *windowdata;
|
SDL_WindowData *windowdata;
|
||||||
Display *display = data->display;
|
Display *display = data->display;
|
||||||
int screen = displaydata->screen;
|
int screen = displaydata->screen;
|
||||||
@@ -934,6 +934,75 @@ static int X11_CatchAnyError(Display *d, XErrorEvent *e)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void X11_ExternalResizeMoveSync(SDL_Window *window)
|
||||||
|
{
|
||||||
|
SDL_WindowData *data = window->internal;
|
||||||
|
Display *display = data->videodata->display;
|
||||||
|
int (*prev_handler)(Display *, XErrorEvent *);
|
||||||
|
unsigned int childCount;
|
||||||
|
Window childReturn, root, parent;
|
||||||
|
Window *children;
|
||||||
|
XWindowAttributes attrs;
|
||||||
|
Uint64 timeout = 0;
|
||||||
|
int x, y;
|
||||||
|
const bool send_move = !!(data->pending_operation & X11_PENDING_OP_MOVE);
|
||||||
|
const bool send_resize = !!(data->pending_operation & X11_PENDING_OP_RESIZE);
|
||||||
|
|
||||||
|
X11_XSync(display, False);
|
||||||
|
X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount);
|
||||||
|
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
|
||||||
|
|
||||||
|
/* Wait a brief time to see if the window manager decided to let the move or resize happen.
|
||||||
|
* If the window changes at all, even to an unexpected value, we break out.
|
||||||
|
*/
|
||||||
|
timeout = SDL_GetTicksNS() + SDL_MS_TO_NS(100);
|
||||||
|
while (true) {
|
||||||
|
caught_x11_error = false;
|
||||||
|
X11_XSync(display, False);
|
||||||
|
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
||||||
|
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
|
||||||
|
attrs.x, attrs.y, &x, &y, &childReturn);
|
||||||
|
SDL_GlobalToRelativeForWindow(window, x, y, &x, &y);
|
||||||
|
|
||||||
|
if (!caught_x11_error) {
|
||||||
|
if ((data->pending_operation & X11_PENDING_OP_MOVE) && (x == data->expected.x + data->border_left && y == data->expected.y + data->border_top)) {
|
||||||
|
data->pending_operation &= ~X11_PENDING_OP_MOVE;
|
||||||
|
}
|
||||||
|
if ((data->pending_operation & X11_PENDING_OP_RESIZE) && (attrs.width == data->expected.w && attrs.height == data->expected.h)) {
|
||||||
|
data->pending_operation &= ~X11_PENDING_OP_RESIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->pending_operation == X11_PENDING_OP_NONE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GetTicksNS() >= timeout) {
|
||||||
|
// Timed out without the expected values. Update the requested data so future sync calls won't block.
|
||||||
|
data->pending_operation &= ~(X11_PENDING_OP_MOVE | X11_PENDING_OP_RESIZE);
|
||||||
|
data->expected.x = x;
|
||||||
|
data->expected.y = y;
|
||||||
|
data->expected.w = attrs.width;
|
||||||
|
data->expected.h = attrs.height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!caught_x11_error) {
|
||||||
|
if (send_move) {
|
||||||
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y);
|
||||||
|
}
|
||||||
|
if (send_resize) {
|
||||||
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, attrs.width, attrs.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
X11_XSetErrorHandler(prev_handler);
|
||||||
|
caught_x11_error = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait a brief time, or not, to see if the window manager decided to move/resize the window.
|
/* Wait a brief time, or not, to see if the window manager decided to move/resize the window.
|
||||||
* Send MOVED and RESIZED window events */
|
* Send MOVED and RESIZED window events */
|
||||||
static bool X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, Uint64 param_timeout)
|
static bool X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, Uint64 param_timeout)
|
||||||
@@ -1214,9 +1283,10 @@ void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
|
|
||||||
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
|
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
|
||||||
|
|
||||||
sizehints->min_width = sizehints->max_width = window->pending.w;
|
data->expected.w = sizehints->min_width = sizehints->max_width = window->pending.w;
|
||||||
sizehints->min_height = sizehints->max_height = window->pending.h;
|
data->expected.h = sizehints->min_height = sizehints->max_height = window->pending.h;
|
||||||
sizehints->flags |= PMinSize | PMaxSize;
|
sizehints->flags |= PMinSize | PMaxSize;
|
||||||
|
data->pending_operation |= X11_PENDING_OP_RESIZE;
|
||||||
|
|
||||||
X11_XSetWMNormalHints(display, data->xwindow, sizehints);
|
X11_XSetWMNormalHints(display, data->xwindow, sizehints);
|
||||||
|
|
||||||
@@ -1695,6 +1765,11 @@ void X11_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
|
|
||||||
void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||||
{
|
{
|
||||||
|
// Don't restore the window the first time it is being shown.
|
||||||
|
if (!window->internal->was_shown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (window->internal->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_MINIMIZE)) {
|
if (window->internal->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_MINIMIZE)) {
|
||||||
SDL_SyncWindow(window);
|
SDL_SyncWindow(window);
|
||||||
}
|
}
|
||||||
@@ -1729,6 +1804,10 @@ static SDL_FullscreenResult X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this,
|
|||||||
Atom _NET_WM_STATE = data->videodata->atoms._NET_WM_STATE;
|
Atom _NET_WM_STATE = data->videodata->atoms._NET_WM_STATE;
|
||||||
Atom _NET_WM_STATE_FULLSCREEN = data->videodata->atoms._NET_WM_STATE_FULLSCREEN;
|
Atom _NET_WM_STATE_FULLSCREEN = data->videodata->atoms._NET_WM_STATE_FULLSCREEN;
|
||||||
|
|
||||||
|
if (!data->was_shown && fullscreen == SDL_FULLSCREEN_OP_LEAVE) {
|
||||||
|
return SDL_FULLSCREEN_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
if (X11_IsWindowMapped(_this, window)) {
|
if (X11_IsWindowMapped(_this, window)) {
|
||||||
XEvent e;
|
XEvent e;
|
||||||
|
|
||||||
@@ -2223,6 +2302,15 @@ void X11_ShowWindowSystemMenu(SDL_Window *window, int x, int y)
|
|||||||
|
|
||||||
bool X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
bool X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||||
{
|
{
|
||||||
|
SDL_WindowData *data = window->internal;
|
||||||
|
|
||||||
|
// If the window is external and has only a pending resize or move event, use the special external sync path to avoid processing events.
|
||||||
|
if ((window->flags & SDL_WINDOW_EXTERNAL) &&
|
||||||
|
(data->pending_operation & ~(X11_PENDING_OP_RESIZE | X11_PENDING_OP_MOVE)) == X11_PENDING_OP_NONE) {
|
||||||
|
X11_ExternalResizeMoveSync(window);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const Uint64 current_time = SDL_GetTicksNS();
|
const Uint64 current_time = SDL_GetTicksNS();
|
||||||
Uint64 timeout = 0;
|
Uint64 timeout = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ struct SDL_WindowData
|
|||||||
bool pending_move;
|
bool pending_move;
|
||||||
SDL_Point pending_move_point;
|
SDL_Point pending_move_point;
|
||||||
XConfigureEvent last_xconfigure;
|
XConfigureEvent last_xconfigure;
|
||||||
|
XConfigureEvent pending_xconfigure;
|
||||||
struct SDL_VideoData *videodata;
|
struct SDL_VideoData *videodata;
|
||||||
unsigned long user_time;
|
unsigned long user_time;
|
||||||
Atom xdnd_req;
|
Atom xdnd_req;
|
||||||
@@ -115,6 +116,9 @@ struct SDL_WindowData
|
|||||||
bool previous_borders_nonzero;
|
bool previous_borders_nonzero;
|
||||||
bool toggle_borders;
|
bool toggle_borders;
|
||||||
bool fullscreen_borders_forced_on;
|
bool fullscreen_borders_forced_on;
|
||||||
|
bool was_shown;
|
||||||
|
bool emit_size_move_after_property_notify;
|
||||||
|
bool tracking_mouse_outside_window;
|
||||||
SDL_HitTestResult hit_test_result;
|
SDL_HitTestResult hit_test_result;
|
||||||
|
|
||||||
XPoint xim_spot;
|
XPoint xim_spot;
|
||||||
|
|||||||
@@ -467,15 +467,17 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
|||||||
SDL_SendPenAxis(0, pen->pen, window, (SDL_PenAxis) i, axes[i]);
|
SDL_SendPenAxis(0, pen->pen, window, (SDL_PenAxis) i, axes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!pointer_emulated && xev->deviceid == videodata->xinput_master_pointer_device) {
|
} else {
|
||||||
// Use the master device for non-relative motion, as the slave devices can seemingly lag behind.
|
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
if (!mouse->relative_mode) {
|
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
|
||||||
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
|
if (!mouse->relative_mode && !pointer_emulated && window &&
|
||||||
if (window) {
|
(xev->deviceid == videodata->xinput_master_pointer_device || window->internal->tracking_mouse_outside_window)) {
|
||||||
X11_ProcessHitTest(_this, window->internal, (float)xev->event_x, (float)xev->event_y, false);
|
/* Use the master device for non-relative motion, as the slave devices can seemingly lag behind, unless
|
||||||
SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, (float)xev->event_x, (float)xev->event_y);
|
* tracking the mouse outside the window, in which case the slave devices deliver coordinates, while the
|
||||||
}
|
* master does not.
|
||||||
|
*/
|
||||||
|
X11_ProcessHitTest(_this, window->internal, (float)xev->event_x, (float)xev->event_y, false);
|
||||||
|
SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, (float)xev->event_x, (float)xev->event_y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -959,6 +959,36 @@ static int SDLCALL surface_testBlitBlendMul(void *arg)
|
|||||||
return TEST_COMPLETED;
|
return TEST_COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests blitting invalid surfaces.
|
||||||
|
*/
|
||||||
|
static int SDLCALL surface_testBlitInvalid(void *arg)
|
||||||
|
{
|
||||||
|
SDL_Surface *valid, *invalid;
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
valid = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA8888);
|
||||||
|
SDLTest_AssertCheck(valid != NULL, "Check surface creation");
|
||||||
|
invalid = SDL_CreateSurface(0, 0, SDL_PIXELFORMAT_RGBA8888);
|
||||||
|
SDLTest_AssertCheck(invalid != NULL, "Check surface creation");
|
||||||
|
SDLTest_AssertCheck(invalid->pixels == NULL, "Check surface pixels are NULL");
|
||||||
|
|
||||||
|
result = SDL_BlitSurface(invalid, NULL, valid, NULL);
|
||||||
|
SDLTest_AssertCheck(result == true, "SDL_BlitSurface(invalid, NULL, valid, NULL), result = %s\n", result ? "true" : "false");
|
||||||
|
result = SDL_BlitSurface(valid, NULL, invalid, NULL);
|
||||||
|
SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, NULL, invalid, NULL), result = %s\n", result ? "true" : "false");
|
||||||
|
|
||||||
|
result = SDL_BlitSurfaceScaled(invalid, NULL, valid, NULL, SDL_SCALEMODE_NEAREST);
|
||||||
|
SDLTest_AssertCheck(result == false, "SDL_BlitSurfaceScaled(invalid, NULL, valid, NULL, SDL_SCALEMODE_NEAREST), result = %s\n", result ? "true" : "false");
|
||||||
|
result = SDL_BlitSurfaceScaled(valid, NULL, invalid, NULL, SDL_SCALEMODE_NEAREST);
|
||||||
|
SDLTest_AssertCheck(result == false, "SDL_BlitSurfaceScaled(valid, NULL, invalid, NULL, SDL_SCALEMODE_NEAREST), result = %s\n", result ? "true" : "false");
|
||||||
|
|
||||||
|
SDL_DestroySurface(valid);
|
||||||
|
SDL_DestroySurface(invalid);
|
||||||
|
|
||||||
|
return TEST_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
static int SDLCALL surface_testOverflow(void *arg)
|
static int SDLCALL surface_testOverflow(void *arg)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@@ -1630,6 +1660,10 @@ static const SDLTest_TestCaseReference surfaceTestBlitBlendMul = {
|
|||||||
surface_testBlitBlendMul, "surface_testBlitBlendMul", "Tests blitting routines with mul blending mode.", TEST_ENABLED
|
surface_testBlitBlendMul, "surface_testBlitBlendMul", "Tests blitting routines with mul blending mode.", TEST_ENABLED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const SDLTest_TestCaseReference surfaceTestBlitInvalid = {
|
||||||
|
surface_testBlitInvalid, "surface_testBlitInvalid", "Tests blitting routines with invalid surfaces.", TEST_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
static const SDLTest_TestCaseReference surfaceTestOverflow = {
|
static const SDLTest_TestCaseReference surfaceTestOverflow = {
|
||||||
surface_testOverflow, "surface_testOverflow", "Test overflow detection.", TEST_ENABLED
|
surface_testOverflow, "surface_testOverflow", "Test overflow detection.", TEST_ENABLED
|
||||||
};
|
};
|
||||||
@@ -1678,6 +1712,7 @@ static const SDLTest_TestCaseReference *surfaceTests[] = {
|
|||||||
&surfaceTestBlitBlendAddPremultiplied,
|
&surfaceTestBlitBlendAddPremultiplied,
|
||||||
&surfaceTestBlitBlendMod,
|
&surfaceTestBlitBlendMod,
|
||||||
&surfaceTestBlitBlendMul,
|
&surfaceTestBlitBlendMul,
|
||||||
|
&surfaceTestBlitInvalid,
|
||||||
&surfaceTestOverflow,
|
&surfaceTestOverflow,
|
||||||
&surfaceTestFlip,
|
&surfaceTestFlip,
|
||||||
&surfaceTestPalette,
|
&surfaceTestPalette,
|
||||||
|
|||||||
+4
-4
@@ -15,8 +15,9 @@
|
|||||||
#include <SDL3/SDL_main.h>
|
#include <SDL3/SDL_main.h>
|
||||||
#include <SDL3/SDL_test.h>
|
#include <SDL3/SDL_test.h>
|
||||||
|
|
||||||
const SDL_DialogFileFilter filters[3] = {
|
const SDL_DialogFileFilter filters[] = {
|
||||||
{ "All files", "*" },
|
{ "All files", "*" },
|
||||||
|
{ "SVI Session Indexes", "index;svi-index;index.pb" },
|
||||||
{ "JPG images", "jpg;jpeg" },
|
{ "JPG images", "jpg;jpeg" },
|
||||||
{ "PNG images", "png" }
|
{ "PNG images", "png" }
|
||||||
};
|
};
|
||||||
@@ -54,7 +55,6 @@ int main(int argc, char *argv[])
|
|||||||
const SDL_FRect open_folder_rect = { 370, 50, 220, 140 };
|
const SDL_FRect open_folder_rect = { 370, 50, 220, 140 };
|
||||||
int i;
|
int i;
|
||||||
const char *initial_path = NULL;
|
const char *initial_path = NULL;
|
||||||
const int nfilters = sizeof(filters) / sizeof(*filters);
|
|
||||||
|
|
||||||
/* Initialize test framework */
|
/* Initialize test framework */
|
||||||
state = SDLTest_CommonCreateState(argv, 0);
|
state = SDLTest_CommonCreateState(argv, 0);
|
||||||
@@ -112,11 +112,11 @@ int main(int argc, char *argv[])
|
|||||||
* - Nonzero if the user is allowed to choose multiple entries (not for SDL_ShowSaveFileDialog)
|
* - Nonzero if the user is allowed to choose multiple entries (not for SDL_ShowSaveFileDialog)
|
||||||
*/
|
*/
|
||||||
if (SDL_PointInRectFloat(&p, &open_file_rect)) {
|
if (SDL_PointInRectFloat(&p, &open_file_rect)) {
|
||||||
SDL_ShowOpenFileDialog(callback, NULL, w, filters, nfilters, initial_path, 1);
|
SDL_ShowOpenFileDialog(callback, NULL, w, filters, SDL_arraysize(filters), initial_path, 1);
|
||||||
} else if (SDL_PointInRectFloat(&p, &open_folder_rect)) {
|
} else if (SDL_PointInRectFloat(&p, &open_folder_rect)) {
|
||||||
SDL_ShowOpenFolderDialog(callback, NULL, w, initial_path, 1);
|
SDL_ShowOpenFolderDialog(callback, NULL, w, initial_path, 1);
|
||||||
} else if (SDL_PointInRectFloat(&p, &save_file_rect)) {
|
} else if (SDL_PointInRectFloat(&p, &save_file_rect)) {
|
||||||
SDL_ShowSaveFileDialog(callback, NULL, w, filters, nfilters, initial_path);
|
SDL_ShowSaveFileDialog(callback, NULL, w, filters, SDL_arraysize(filters), initial_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user