Compare commits
245
Commits
main
...
release-3.2.14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d604353a5 | ||
|
|
8410e11ecb | ||
|
|
9f8161bf4a | ||
|
|
c038d6f7f8 | ||
|
|
2fff37fffc | ||
|
|
6feb86be71 | ||
|
|
ed22220bc6 | ||
|
|
219cb1a59d | ||
|
|
71bd25a893 | ||
|
|
01ef4c46a1 | ||
|
|
64f728ec48 | ||
|
|
ba10adf1fb | ||
|
|
c18aa99358 | ||
|
|
3498412611 | ||
|
|
8c1b3ff210 | ||
|
|
1870052af6 | ||
|
|
3b1e3d5176 | ||
|
|
cdf26c6e97 | ||
|
|
9f1a1405a6 | ||
|
|
6e97d8d1b3 | ||
|
|
9d9a24d325 | ||
|
|
0897f4a7d1 | ||
|
|
5aec645191 | ||
|
|
07c33068f3 | ||
|
|
d684e5d57e | ||
|
|
219500d95c | ||
|
|
810addf7ae | ||
|
|
4ef077ca52 | ||
|
|
7d2275c4dc | ||
|
|
cbd8917047 | ||
|
|
c98a19401c | ||
|
|
434836c480 | ||
|
|
50d02ad732 | ||
|
|
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 | ||
|
|
877399b2b2 | ||
|
|
3f059376ac | ||
|
|
30a6d01cc5 | ||
|
|
b6fb47aa70 | ||
|
|
7ecae856e5 | ||
|
|
5db7694f22 | ||
|
|
366294e1c5 | ||
|
|
4d966ff546 | ||
|
|
6b665066f0 | ||
|
|
519011f271 | ||
|
|
5c224a3221 | ||
|
|
4b8c38e7ba | ||
|
|
16f6c1058c | ||
|
|
7939309520 | ||
|
|
cec6073085 | ||
|
|
a9f121f3f7 | ||
|
|
361218ce15 | ||
|
|
04dcfada00 | ||
|
|
d73ad0ef18 | ||
|
|
a1b888f622 | ||
|
|
d6267afcb9 | ||
|
|
b8325be9cf | ||
|
|
e77ef86f09 | ||
|
|
951ba597ed | ||
|
|
ab5e178dab | ||
|
|
04dace6c75 | ||
|
|
013918cd83 | ||
|
|
996466e855 | ||
|
|
61e7878ac0 | ||
|
|
c067cb4e7d | ||
|
|
38697dd812 | ||
|
|
f03572335a | ||
|
|
d8837edfa2 | ||
|
|
e5f8043037 | ||
|
|
134b57f6f5 | ||
|
|
072e760197 | ||
|
|
d37a3e2a71 | ||
|
|
ed8e7e85f0 | ||
|
|
eb9faad124 | ||
|
|
3ed80843fe | ||
|
|
4029521a63 | ||
|
|
f971a59746 | ||
|
|
5836266bfb | ||
|
|
ed893bde04 | ||
|
|
a934a36a18 | ||
|
|
59857acd08 | ||
|
|
8129b637f3 | ||
|
|
9e1675671d | ||
|
|
d39d951f89 | ||
|
|
10ed6f49a9 | ||
|
|
c2c848a752 | ||
|
|
8b191c3ca6 | ||
|
|
06a412cd68 | ||
|
|
b74609d5f3 | ||
|
|
d8756582f9 | ||
|
|
ff90984dc3 | ||
|
|
81952f9f96 | ||
|
|
d0122ff624 | ||
|
|
7a36aa37aa | ||
|
|
464cb0ab6e | ||
|
|
ac21e3ef3f | ||
|
|
a5b51669fb | ||
|
|
0ac030549b | ||
|
|
6f1afe7084 | ||
|
|
6302589829 | ||
|
|
3225d31679 | ||
|
|
ae05ab280d | ||
|
|
51a6cb2cf5 | ||
|
|
daf468e141 | ||
|
|
cd673c8254 | ||
|
|
3f13c0b36d | ||
|
|
3e34720851 | ||
|
|
0799237d74 | ||
|
|
53f64e40c4 | ||
|
|
a530df20b2 | ||
|
|
b958189c92 | ||
|
|
341f910835 | ||
|
|
84dff407d4 | ||
|
|
21e6c5814c | ||
|
|
776f0a685c | ||
|
|
9f32fafe21 | ||
|
|
74b3b8e9e3 | ||
|
|
fa4a9ba74e | ||
|
|
9a6f8a2512 | ||
|
|
1173bc2dde | ||
|
|
ada55bd887 | ||
|
|
fe97cff7d1 | ||
|
|
8cdeb1a35a | ||
|
|
7c82171a85 | ||
|
|
2d2085c80b | ||
|
|
03a4eea0ef | ||
|
|
fec3e2cd45 | ||
|
|
2aec1c2ef6 | ||
|
|
b32cd4f84b | ||
|
|
550bdc658a | ||
|
|
d75ba9c2d2 | ||
|
|
2477f7f982 | ||
|
|
e454d7d4be | ||
|
|
cd8bffb2dd | ||
|
|
9646e3cc1b | ||
|
|
1a2362ebf1 | ||
|
|
f6864924f7 | ||
|
|
6b3dafa4d3 | ||
|
|
5c0c5d2816 | ||
|
|
de11dd3d60 | ||
|
|
ac09af2600 | ||
|
|
26d1afa29c | ||
|
|
6aab3b9da8 | ||
|
|
d959719a3d | ||
|
|
5a7b17fec5 | ||
|
|
1d6bb62870 | ||
|
|
0c3603d893 | ||
|
|
38a5bca892 | ||
|
|
70a289076a | ||
|
|
1d0ecf982f | ||
|
|
18d93d11e1 | ||
|
|
110a832f5c | ||
|
|
6a9e970880 | ||
|
|
4e3058ce82 | ||
|
|
bc6307a872 |
No files matched your search
+6
-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.6")
|
project(SDL3 LANGUAGES C VERSION "3.2.14")
|
||||||
|
|
||||||
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)
|
||||||
@@ -2188,6 +2188,7 @@ elseif(APPLE)
|
|||||||
set(SDL_CAMERA_DRIVER_COREMEDIA 1)
|
set(SDL_CAMERA_DRIVER_COREMEDIA 1)
|
||||||
set(HAVE_CAMERA TRUE)
|
set(HAVE_CAMERA TRUE)
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/coremedia/*.m")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/coremedia/*.m")
|
||||||
|
set(SDL_FRAMEWORK_AVFOUNDATION 1)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -3016,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)
|
||||||
@@ -3287,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)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
SDL supports a number of development environments:
|
SDL supports a number of development environments:
|
||||||
- [CMake](docs/INTRO-cmake.md)
|
- [CMake](docs/INTRO-cmake.md)
|
||||||
- [Visual Studio on Windows](docs/INTRO-visualstudio.md)
|
- [Visual Studio on Windows](docs/INTRO-visualstudio.md)
|
||||||
|
- [gcc on Windows](docs/INTRO-mingw.md)
|
||||||
- [Xcode on Apple platforms](docs/INTRO-xcode.md)
|
- [Xcode on Apple platforms](docs/INTRO-xcode.md)
|
||||||
- [Android Studio](docs/INTRO-androidstudio.md)
|
- [Android Studio](docs/INTRO-androidstudio.md)
|
||||||
- [Emscripten for web](docs/INTRO-emscripten.md)
|
- [Emscripten for web](docs/INTRO-emscripten.md)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
|
|
||||||
This is a list of major changes in SDL's version history.
|
This is a list of major changes in SDL's version history.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
3.2.10:
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
* Added SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT to control whether XSelectInput() should be called on external windows to enable input events.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
3.2.4:
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
* Added SDL_StretchSurface()
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
3.2.0:
|
3.2.0:
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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.6</string>
|
<string>3.2.14</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>SDLX</string>
|
<string>SDLX</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>3.2.6</string>
|
<string>3.2.14</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.6.0;
|
DYLIB_CURRENT_VERSION = 201.14.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.6;
|
MARKETING_VERSION = 3.2.14;
|
||||||
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.6.0;
|
DYLIB_CURRENT_VERSION = 201.14.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.6;
|
MARKETING_VERSION = 3.2.14;
|
||||||
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.6
|
Title SDL 3.2.14
|
||||||
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
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ plugins {
|
|||||||
def buildWithCMake = project.hasProperty('BUILD_WITH_CMAKE');
|
def buildWithCMake = project.hasProperty('BUILD_WITH_CMAKE');
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace "org.libsdl.app"
|
namespace = "org.libsdl.app"
|
||||||
compileSdkVersion 35
|
compileSdkVersion 35
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
@@ -14,12 +14,12 @@ android {
|
|||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
ndkBuild {
|
ndkBuild {
|
||||||
arguments "APP_PLATFORM=android-19"
|
arguments "APP_PLATFORM=android-21"
|
||||||
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||||
abiFilters 'arm64-v8a'
|
abiFilters 'arm64-v8a'
|
||||||
}
|
}
|
||||||
cmake {
|
cmake {
|
||||||
arguments "-DANDROID_PLATFORM=android-19", "-DANDROID_STL=c++_static"
|
arguments "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_static"
|
||||||
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||||
abiFilters 'arm64-v8a'
|
abiFilters 'arm64-v8a'
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ android {
|
|||||||
|
|
||||||
}
|
}
|
||||||
lint {
|
lint {
|
||||||
abortOnError false
|
abortOnError = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 = 6;
|
private static final int SDL_MICRO_VERSION = 14;
|
||||||
/*
|
/*
|
||||||
// Display InputType.SOURCE/CLASS of events and devices
|
// Display InputType.SOURCE/CLASS of events and devices
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -424,7 +424,11 @@ sub dewikify_chunk {
|
|||||||
$str .= "\n```$codelang\n$code\n```\n";
|
$str .= "\n```$codelang\n$code\n```\n";
|
||||||
}
|
}
|
||||||
} elsif ($dewikify_mode eq 'manpage') {
|
} elsif ($dewikify_mode eq 'manpage') {
|
||||||
$str =~ s/\./\\[char46]/gms; # make sure these can't become control codes.
|
# make sure these can't become part of roff syntax.
|
||||||
|
$str =~ s/\./\\[char46]/gms;
|
||||||
|
$str =~ s/"/\\(dq/gms;
|
||||||
|
$str =~ s/'/\\(aq/gms;
|
||||||
|
|
||||||
if ($wikitype eq 'mediawiki') {
|
if ($wikitype eq 'mediawiki') {
|
||||||
# Dump obvious wikilinks.
|
# Dump obvious wikilinks.
|
||||||
if (defined $apiprefixregex) {
|
if (defined $apiprefixregex) {
|
||||||
@@ -449,33 +453,52 @@ sub dewikify_chunk {
|
|||||||
# bullets
|
# bullets
|
||||||
$str =~ s/^\* /\n\\\(bu /gm;
|
$str =~ s/^\* /\n\\\(bu /gm;
|
||||||
} elsif ($wikitype eq 'md') {
|
} elsif ($wikitype eq 'md') {
|
||||||
|
# bullets
|
||||||
|
$str =~ s/^\- /\n\\(bu /gm;
|
||||||
|
# merge paragraphs
|
||||||
|
$str =~ s/^[ \t]+//gm;
|
||||||
|
$str =~ s/([^\-\n])\n([^\-\n])/$1 $2/g;
|
||||||
|
$str =~ s/\n\n/\n.PP\n/g;
|
||||||
|
|
||||||
# Dump obvious wikilinks.
|
# Dump obvious wikilinks.
|
||||||
if (defined $apiprefixregex) {
|
if (defined $apiprefixregex) {
|
||||||
$str =~ s/\[(\`?$apiprefixregex[a-zA-Z0-9_]+\`?)\]\($apiprefixregex[a-zA-Z0-9_]+\)/\n.BR $1\n/gms;
|
my $apr = $apiprefixregex;
|
||||||
|
if(!($apr =~ /\A\(.*\)\Z/s)) {
|
||||||
|
# we're relying on the apiprefixregex having a capturing group.
|
||||||
|
$apr = "(" . $apr . ")";
|
||||||
|
}
|
||||||
|
$str =~ s/(\S*?)\[\`?($apr[a-zA-Z0-9_]+)\`?\]\($apr[a-zA-Z0-9_]+\)(\S*)\s*/\n.BR "" "$1" "$2" "$5"\n/gm;
|
||||||
|
# handle cases like "[x](x), [y](y), [z](z)" being separated.
|
||||||
|
while($str =~ s/(\.BR[^\n]*)\n\n\.BR/$1\n.BR/gm) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
# links
|
# links
|
||||||
$str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\n.URL "$2" "$1"\n/g;
|
$str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\n.URL "$2" "$1"\n/g;
|
||||||
|
|
||||||
# <code></code> is also popular. :/
|
# <code></code> is also popular. :/
|
||||||
$str =~ s/\s*\`(.*?)\`\s*/\n.BR $1\n/gms;
|
$str =~ s/\s*(\S*?)\`([^\n]*?)\`(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms;
|
||||||
|
|
||||||
# bold+italic (this looks bad, just make it bold).
|
# bold+italic (this looks bad, just make it bold).
|
||||||
$str =~ s/\s*\*\*\*(.*?)\*\*\*\s*/\n.B $1\n/gms;
|
$str =~ s/\s*(\S*?)\*\*\*([^\n]*?)\*\*\*(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms;
|
||||||
|
|
||||||
# bold
|
# bold
|
||||||
$str =~ s/\s*\*\*(.*?)\*\*\s*/\n.B $1\n/gms;
|
$str =~ s/\s*(\S*?)\*\*([^\n]*?)\*\*(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms;
|
||||||
|
|
||||||
# italic
|
# italic
|
||||||
$str =~ s/\s*\*(.*?)\*\s*/\n.I $1\n/gms;
|
$str =~ s/\s*(\S*?)\*([^\n]*?)\*(\S*)\s*/\n.IR "" "$1" "$2" "$3"\n/gms;
|
||||||
|
|
||||||
# bullets
|
|
||||||
$str =~ s/^\- /\n\\\(bu /gm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# cleanup unnecessary quotes
|
||||||
|
$str =~ s/(\.[IB]R?)(.*?) ""\n/$1$2\n/gm;
|
||||||
|
$str =~ s/(\.[IB]R?) "" ""(.*?)\n/$1$2\n/gm;
|
||||||
|
$str =~ s/"(\S+)"/$1/gm;
|
||||||
|
# cleanup unnecessary whitespace
|
||||||
|
$str =~ s/ +\n/\n/gm;
|
||||||
|
|
||||||
if (defined $code) {
|
if (defined $code) {
|
||||||
$code =~ s/\A\n+//gms;
|
$code =~ s/\A\n+//gms;
|
||||||
$code =~ s/\n+\Z//gms;
|
$code =~ s/\n+\Z//gms;
|
||||||
|
$code =~ s/\\/\\(rs/gms;
|
||||||
if ($dewikify_manpage_code_indent) {
|
if ($dewikify_manpage_code_indent) {
|
||||||
$str .= "\n.IP\n"
|
$str .= "\n.IP\n"
|
||||||
} else {
|
} else {
|
||||||
@@ -580,7 +603,7 @@ sub dewikify {
|
|||||||
$retval .= dewikify_chunk($wikitype, $1, $2, $3);
|
$retval .= dewikify_chunk($wikitype, $1, $2, $3);
|
||||||
}
|
}
|
||||||
} elsif ($wikitype eq 'md') {
|
} elsif ($wikitype eq 'md') {
|
||||||
while ($str =~ s/\A(.*?)\n```(.*?)\n(.*?)\n```\n//ms) {
|
while ($str =~ s/\A(.*?)\n?```(.*?)\n(.*?)\n```\n//ms) {
|
||||||
$retval .= dewikify_chunk($wikitype, $1, $2, $3);
|
$retval .= dewikify_chunk($wikitype, $1, $2, $3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2765,7 +2788,6 @@ __EOF__
|
|||||||
my $wikitype = $wikitypes{$sym};
|
my $wikitype = $wikitypes{$sym};
|
||||||
my $sectionsref = $wikisyms{$sym};
|
my $sectionsref = $wikisyms{$sym};
|
||||||
my $remarks = $sectionsref->{'Remarks'};
|
my $remarks = $sectionsref->{'Remarks'};
|
||||||
my $params = $sectionsref->{'Function Parameters'};
|
|
||||||
my $returns = $sectionsref->{'Return Value'};
|
my $returns = $sectionsref->{'Return Value'};
|
||||||
my $version = $sectionsref->{'Version'};
|
my $version = $sectionsref->{'Version'};
|
||||||
my $threadsafety = $sectionsref->{'Thread Safety'};
|
my $threadsafety = $sectionsref->{'Thread Safety'};
|
||||||
@@ -2773,6 +2795,23 @@ __EOF__
|
|||||||
my $examples = $sectionsref->{'Code Examples'};
|
my $examples = $sectionsref->{'Code Examples'};
|
||||||
my $deprecated = $sectionsref->{'Deprecated'};
|
my $deprecated = $sectionsref->{'Deprecated'};
|
||||||
my $headerfile = $manpageheaderfiletext;
|
my $headerfile = $manpageheaderfiletext;
|
||||||
|
|
||||||
|
my $params = undef;
|
||||||
|
|
||||||
|
if ($symtype == -1) { # category documentation block.
|
||||||
|
# nothing to be done here.
|
||||||
|
} elsif (($symtype == 1) || (($symtype == 5))) { # we'll assume a typedef (5) with a \param is a function pointer typedef.
|
||||||
|
$params = $sectionsref->{'Function Parameters'};
|
||||||
|
} elsif ($symtype == 2) {
|
||||||
|
$params = $sectionsref->{'Macro Parameters'};
|
||||||
|
} elsif ($symtype == 3) {
|
||||||
|
$params = $sectionsref->{'Fields'};
|
||||||
|
} elsif ($symtype == 4) {
|
||||||
|
$params = $sectionsref->{'Values'};
|
||||||
|
} else {
|
||||||
|
die("Unexpected symtype $symtype");
|
||||||
|
}
|
||||||
|
|
||||||
$headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g;
|
$headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g;
|
||||||
$headerfile .= "\n";
|
$headerfile .= "\n";
|
||||||
|
|
||||||
@@ -2839,18 +2878,22 @@ __EOF__
|
|||||||
$str .= dewikify($wikitype, $deprecated) . "\n";
|
$str .= dewikify($wikitype, $deprecated) . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $incfile = $mainincludefname;
|
||||||
if (defined $headerfile) {
|
if (defined $headerfile) {
|
||||||
$str .= ".SH HEADER FILE\n";
|
if($headerfile =~ /Defined in (.*)/) {
|
||||||
$str .= dewikify($wikitype, $headerfile) . "\n";
|
$incfile = $1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$str .= ".SH SYNOPSIS\n";
|
$str .= ".SH SYNOPSIS\n";
|
||||||
$str .= ".nf\n";
|
$str .= ".nf\n";
|
||||||
$str .= ".B #include \\(dq$mainincludefname\\(dq\n";
|
$str .= ".B #include <$incfile>\n";
|
||||||
$str .= ".PP\n";
|
$str .= ".PP\n";
|
||||||
|
|
||||||
my @decllines = split /\n/, $decl;
|
my @decllines = split /\n/, $decl;
|
||||||
foreach (@decllines) {
|
foreach (@decllines) {
|
||||||
|
$_ =~ s/\\/\\(rs/g; # fix multiline macro defs
|
||||||
|
$_ =~ s/"/\\(dq/g;
|
||||||
$str .= ".BI \"$_\n";
|
$str .= ".BI \"$_\n";
|
||||||
}
|
}
|
||||||
$str .= ".fi\n";
|
$str .= ".fi\n";
|
||||||
@@ -2938,8 +2981,11 @@ __EOF__
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (defined $returns) {
|
if (defined $returns) {
|
||||||
|
# Chop datatype in parentheses off the front.
|
||||||
|
if(!($returns =~ s/\A\([^\[]*\[[^\]]*\]\([^\)]*\)[^\)]*\) //ms)) {
|
||||||
|
$returns =~ s/\A\([^\)]*\) //ms;
|
||||||
|
}
|
||||||
$returns = dewikify($wikitype, $returns);
|
$returns = dewikify($wikitype, $returns);
|
||||||
$returns =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front.
|
|
||||||
$str .= ".SH RETURN VALUE\n";
|
$str .= ".SH RETURN VALUE\n";
|
||||||
$str .= "$returns\n";
|
$str .= "$returns\n";
|
||||||
}
|
}
|
||||||
@@ -2975,6 +3021,8 @@ __EOF__
|
|||||||
s/\A\/*//;
|
s/\A\/*//;
|
||||||
s/\A\.BR\s+//; # dewikify added this, but we want to handle it.
|
s/\A\.BR\s+//; # dewikify added this, but we want to handle it.
|
||||||
s/\A\.I\s+//; # dewikify added this, but we want to handle it.
|
s/\A\.I\s+//; # dewikify added this, but we want to handle it.
|
||||||
|
s/\A\.PP\s*//; # dewikify added this, but we want to handle it.
|
||||||
|
s/\\\(bu//; # dewikify added this, but we want to handle it.
|
||||||
s/\A\s*[\:\*\-]\s*//;
|
s/\A\s*[\:\*\-]\s*//;
|
||||||
s/\A\s+//;
|
s/\A\s+//;
|
||||||
s/\s+\Z//;
|
s/\s+\Z//;
|
||||||
|
|||||||
@@ -823,7 +823,7 @@ macro(CheckPTHREAD)
|
|||||||
if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
|
if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
|
||||||
set(PTHREAD_LDFLAGS "-mt -lpthread")
|
set(PTHREAD_LDFLAGS "-mt -lpthread")
|
||||||
else()
|
else()
|
||||||
set(PTHREAD_LDFLAGS "-pthread -lposix4")
|
set(PTHREAD_LDFLAGS "-pthread")
|
||||||
endif()
|
endif()
|
||||||
elseif(SYSV5)
|
elseif(SYSV5)
|
||||||
set(PTHREAD_CFLAGS "-D_REENTRANT -Kthread")
|
set(PTHREAD_CFLAGS "-D_REENTRANT -Kthread")
|
||||||
|
|||||||
+16
-9
@@ -5,7 +5,12 @@ The easiest way to use SDL is to include it as a subproject in your project.
|
|||||||
|
|
||||||
We'll start by creating a simple project to build and run [hello.c](hello.c)
|
We'll start by creating a simple project to build and run [hello.c](hello.c)
|
||||||
|
|
||||||
Create the file CMakeLists.txt
|
# Get a copy of the SDL source:
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/libsdl-org/SDL.git vendored/SDL
|
||||||
|
```
|
||||||
|
|
||||||
|
# Create the file CMakeLists.txt
|
||||||
```cmake
|
```cmake
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(hello)
|
project(hello)
|
||||||
@@ -25,24 +30,26 @@ add_executable(hello WIN32 hello.c)
|
|||||||
target_link_libraries(hello PRIVATE SDL3::SDL3)
|
target_link_libraries(hello PRIVATE SDL3::SDL3)
|
||||||
```
|
```
|
||||||
|
|
||||||
Build:
|
# Configure and Build:
|
||||||
```sh
|
```sh
|
||||||
cmake -S . -B build
|
cmake -S . -B build
|
||||||
cmake --build build
|
cmake --build build
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
# Run:
|
||||||
- On Windows the executable is in the build Debug directory:
|
The executable should be in the `build` directory:
|
||||||
```sh
|
|
||||||
cd build/Debug
|
|
||||||
./hello
|
|
||||||
```
|
|
||||||
- On other platforms the executable is in the build directory:
|
|
||||||
```sh
|
```sh
|
||||||
cd build
|
cd build
|
||||||
./hello
|
./hello
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If there wasn't an executable there despite the above Build section running successfully, it's likely because you're following this guide using the Visual Studio toolchain, it should instead be in the `build/Debug` directory:
|
||||||
|
```sh
|
||||||
|
cd build/Debug
|
||||||
|
./hello
|
||||||
|
```
|
||||||
|
|
||||||
A more complete example is available at:
|
A more complete example is available at:
|
||||||
|
|
||||||
https://github.com/Ravbug/sdl3-sample
|
https://github.com/Ravbug/sdl3-sample
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# Introduction to SDL with MinGW
|
||||||
|
|
||||||
|
Without getting deep into the history, MinGW is a long running project that aims to bring gcc to Windows. That said, there's many distributions, versions, and forks floating around. We recommend installing [MSYS2](https://www.msys2.org/), as it's the easiest way to get a modern toolchain with a package manager to help with dependency management. This would allow you to follow the MSYS2 section below.
|
||||||
|
|
||||||
|
Otherwise you'll want to follow the "Other Distributions" section below.
|
||||||
|
|
||||||
|
We'll start by creating a simple project to build and run [hello.c](hello.c).
|
||||||
|
|
||||||
|
# MSYS2
|
||||||
|
|
||||||
|
Open the `MSYS2 UCRT64` prompt and then ensure you've installed the following packages. This will get you working toolchain, CMake, Ninja, and of course SDL3.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-sdl3
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create the file CMakeLists.txt
|
||||||
|
```cmake
|
||||||
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
project(hello C CXX)
|
||||||
|
|
||||||
|
find_package(SDL3 REQUIRED)
|
||||||
|
|
||||||
|
add_executable(hello)
|
||||||
|
|
||||||
|
target_sources(hello
|
||||||
|
PRIVATE
|
||||||
|
hello.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(hello SDL3::SDL3)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configure and Build:
|
||||||
|
```sh
|
||||||
|
cmake -S . -B build
|
||||||
|
cmake --build build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run:
|
||||||
|
|
||||||
|
The executable is in the `build` directory:
|
||||||
|
```sh
|
||||||
|
cd build
|
||||||
|
./hello
|
||||||
|
```
|
||||||
|
|
||||||
|
# Other Distributions
|
||||||
|
|
||||||
|
Things can get quite complicated with other distributions of MinGW. If you can't follow [the cmake intro](INTRO-cmake.md), perhaps due to issues getting cmake to understand your toolchain, this section should work.
|
||||||
|
|
||||||
|
## Acquire SDL
|
||||||
|
|
||||||
|
Download the `SDL3-devel-<version>-mingw.zip` asset from [the latest release.](https://github.com/libsdl-org/SDL/releases/latest) Then extract it inside your project folder such that the output of `ls SDL3-<version>` looks like `INSTALL.md LICENSE.txt Makefile README.md cmake i686-w64-mingw32 x86_64-w64-mingw32`.
|
||||||
|
|
||||||
|
## Know your Target Architecture
|
||||||
|
|
||||||
|
It is not uncommon for folks to not realize their distribution is targeting 32bit Windows despite things like the name of the toolchain, or the fact that they're running on a 64bit system. We'll ensure we know up front what we need:
|
||||||
|
|
||||||
|
Create a file named `arch.c` with the following contents:
|
||||||
|
```c
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
int main() {
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
|
||||||
|
size_t ptr_size = sizeof(int*);
|
||||||
|
if (4 == ptr_size) puts("i686-w64-mingw32");
|
||||||
|
else if (8 == ptr_size) puts("x86_64-w64-mingw32");
|
||||||
|
else puts("Unknown Architecture");
|
||||||
|
#else
|
||||||
|
puts("Unknown Architecture");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gcc arch.c
|
||||||
|
./a.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
This should print out which library directory we'll need to use when compiling, keep this value in mind, you'll need to use it when compiling in the next section as `<arch>`. If you get "Unknown Architecture" please [report a bug](https://github.com/libsdl-org/SDL/issues).
|
||||||
|
|
||||||
|
|
||||||
|
## Build and Run
|
||||||
|
|
||||||
|
Now we should have everything needed to compile and run our program. You'll need to ensure to replace `<version>` with the version of the release of SDL3 you downloaded, as well as use the `<arch>` we learned in the previous section.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gcc hello.c -o hello.exe -I SDL3-<version>/<arch>/include -L SDL3-<version>/<arch>/lib -lSDL3 -mwindows
|
||||||
|
cp SDL3-<version>/<arch>/bin/SDL3.dll SDL3.dll
|
||||||
|
./hello.exe
|
||||||
|
```
|
||||||
@@ -5,10 +5,12 @@ The easiest way to use SDL is to include it as a subproject in your project.
|
|||||||
|
|
||||||
We'll start by creating a simple project to build and run [hello.c](hello.c)
|
We'll start by creating a simple project to build and run [hello.c](hello.c)
|
||||||
|
|
||||||
|
- Get a copy of the SDL source, you can clone the repo, or download the "Source Code" asset from [the latest release.](https://github.com/libsdl-org/SDL/releases/latest)
|
||||||
|
- If you've downloaded a release, make sure to extract the contents somewhere you can find it.
|
||||||
- Create a new project in Visual Studio, using the C++ Empty Project template
|
- Create a new project in Visual Studio, using the C++ Empty Project template
|
||||||
- Add hello.c to the Source Files
|
- Add hello.c to the Source Files
|
||||||
- Right click the solution, select add an existing project, navigate to VisualC/SDL and add SDL.vcxproj
|
- Right click the solution, select add an existing project, navigate to `VisualC/SDL` from within the source you cloned or downloaded above and add SDL.vcxproj
|
||||||
- Select your main project and go to Project -> Add Reference and select SDL3
|
- Select your main project and go to Project -> Add -> Reference and select SDL3
|
||||||
- Select your main project and go to Project -> Properties, set the filter at the top to "All Configurations" and "All Platforms", select VC++ Directories and add the SDL include directory to "Include Directories"
|
- Select your main project and go to Project -> Properties, set the filter at the top to "All Configurations" and "All Platforms", select C/C++ -> General and add the SDL include directory to "Additional Include Directories"
|
||||||
- Build and run!
|
- Build and run!
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ not give you any processing time after the events are delivered.
|
|||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
|
|
||||||
int HandleAppEvents(void *userdata, SDL_Event *event)
|
bool HandleAppEvents(void *userdata, SDL_Event *event)
|
||||||
{
|
{
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
@@ -250,12 +250,12 @@ e.g.
|
|||||||
/* Terminate the app.
|
/* Terminate the app.
|
||||||
Shut everything down before returning from this function.
|
Shut everything down before returning from this function.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_LOW_MEMORY:
|
case SDL_EVENT_LOW_MEMORY:
|
||||||
/* You will get this when your app is paused and iOS wants more memory.
|
/* You will get this when your app is paused and iOS wants more memory.
|
||||||
Release as much memory as possible.
|
Release as much memory as possible.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_WILL_ENTER_BACKGROUND:
|
case SDL_EVENT_WILL_ENTER_BACKGROUND:
|
||||||
/* Prepare your app to go into the background. Stop loops, etc.
|
/* Prepare your app to go into the background. Stop loops, etc.
|
||||||
This gets called when the user hits the home button, or gets a call.
|
This gets called when the user hits the home button, or gets a call.
|
||||||
@@ -264,15 +264,15 @@ e.g.
|
|||||||
in addition, you should set the render target to NULL, if you're using
|
in addition, you should set the render target to NULL, if you're using
|
||||||
it, e.g. call SDL_SetRenderTarget(renderer, NULL).
|
it, e.g. call SDL_SetRenderTarget(renderer, NULL).
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_DID_ENTER_BACKGROUND:
|
case SDL_EVENT_DID_ENTER_BACKGROUND:
|
||||||
/* Your app is NOT active at this point. */
|
/* Your app is NOT active at this point. */
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_WILL_ENTER_FOREGROUND:
|
case SDL_EVENT_WILL_ENTER_FOREGROUND:
|
||||||
/* This call happens when your app is coming back to the foreground.
|
/* This call happens when your app is coming back to the foreground.
|
||||||
Restore all your state here.
|
Restore all your state here.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_DID_ENTER_FOREGROUND:
|
case SDL_EVENT_DID_ENTER_FOREGROUND:
|
||||||
/* Restart your loops here.
|
/* Restart your loops here.
|
||||||
Your app is interactive and getting CPU again.
|
Your app is interactive and getting CPU again.
|
||||||
@@ -283,10 +283,10 @@ e.g.
|
|||||||
event SDL_EVENT_RENDER_DEVICE_RESET and recreate your OpenGL context and
|
event SDL_EVENT_RENDER_DEVICE_RESET and recreate your OpenGL context and
|
||||||
restore your textures when you get it, or quit the app.
|
restore your textures when you get it, or quit the app.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
default:
|
default:
|
||||||
/* No special processing, add it to the event queue */
|
/* No special processing, add it to the event queue */
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+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.
|
||||||
|
|
||||||
+8
-8
@@ -65,7 +65,7 @@ not give you any processing time after the events are delivered.
|
|||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
|
|
||||||
int HandleAppEvents(void *userdata, SDL_Event *event)
|
bool HandleAppEvents(void *userdata, SDL_Event *event)
|
||||||
{
|
{
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
@@ -73,37 +73,37 @@ e.g.
|
|||||||
/* Terminate the app.
|
/* Terminate the app.
|
||||||
Shut everything down before returning from this function.
|
Shut everything down before returning from this function.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_LOW_MEMORY:
|
case SDL_EVENT_LOW_MEMORY:
|
||||||
/* You will get this when your app is paused and iOS wants more memory.
|
/* You will get this when your app is paused and iOS wants more memory.
|
||||||
Release as much memory as possible.
|
Release as much memory as possible.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_WILL_ENTER_BACKGROUND:
|
case SDL_EVENT_WILL_ENTER_BACKGROUND:
|
||||||
/* Prepare your app to go into the background. Stop loops, etc.
|
/* Prepare your app to go into the background. Stop loops, etc.
|
||||||
This gets called when the user hits the home button, or gets a call.
|
This gets called when the user hits the home button, or gets a call.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_DID_ENTER_BACKGROUND:
|
case SDL_EVENT_DID_ENTER_BACKGROUND:
|
||||||
/* This will get called if the user accepted whatever sent your app to the background.
|
/* This will get called if the user accepted whatever sent your app to the background.
|
||||||
If the user got a phone call and canceled it, you'll instead get an SDL_EVENT_DID_ENTER_FOREGROUND event and restart your loops.
|
If the user got a phone call and canceled it, you'll instead get an SDL_EVENT_DID_ENTER_FOREGROUND event and restart your loops.
|
||||||
When you get this, you have 5 seconds to save all your state or the app will be terminated.
|
When you get this, you have 5 seconds to save all your state or the app will be terminated.
|
||||||
Your app is NOT active at this point.
|
Your app is NOT active at this point.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_WILL_ENTER_FOREGROUND:
|
case SDL_EVENT_WILL_ENTER_FOREGROUND:
|
||||||
/* This call happens when your app is coming back to the foreground.
|
/* This call happens when your app is coming back to the foreground.
|
||||||
Restore all your state here.
|
Restore all your state here.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
case SDL_EVENT_DID_ENTER_FOREGROUND:
|
case SDL_EVENT_DID_ENTER_FOREGROUND:
|
||||||
/* Restart your loops here.
|
/* Restart your loops here.
|
||||||
Your app is interactive and getting CPU again.
|
Your app is interactive and getting CPU again.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return false;
|
||||||
default:
|
default:
|
||||||
/* No special processing, add it to the event queue */
|
/* No special processing, add it to the event queue */
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ cmake --install build
|
|||||||
|
|
||||||
|
|
||||||
## Compiling a HelloWorld
|
## Compiling a HelloWorld
|
||||||
[PSP Hello World](https://psp-dev.org/doku.php?id=tutorial:hello_world)
|
[PSP Hello World](https://pspdev.github.io/basic_programs.html#hello-world)
|
||||||
|
|
||||||
## To Do
|
## To Do
|
||||||
- PSP Screen Keyboard
|
- PSP Screen Keyboard
|
||||||
|
|||||||
+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.
|
|
||||||
@@ -59,6 +59,10 @@ encounter limitations or behavior that is different from other windowing systems
|
|||||||
`SDL_APP_ID` hint string, the desktop entry file name should match the application ID. For example, if your
|
`SDL_APP_ID` hint string, the desktop entry file name should match the application ID. For example, if your
|
||||||
application ID is set to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`.
|
application ID is set to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`.
|
||||||
|
|
||||||
|
### Keyboard grabs don't work when running under XWayland
|
||||||
|
|
||||||
|
- On GNOME based desktops, the dconf setting `org/gnome/mutter/wayland/xwayland-allow-grabs` must be enabled.
|
||||||
|
|
||||||
## Using custom Wayland windowing protocols with SDL windows
|
## Using custom Wayland windowing protocols with SDL windows
|
||||||
|
|
||||||
Under normal operation, an `SDL_Window` corresponds to an XDG toplevel window, which provides a standard desktop window.
|
Under normal operation, an `SDL_Window` corresponds to an XDG toplevel window, which provides a standard desktop window.
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main include header for the SDL library, version 3.2.6
|
* Main include header for the SDL library, version 3.2.14
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1717,7 +1717,7 @@ typedef void (SDLCALL *SDL_AudioStreamCallback)(void *userdata, SDL_AudioStream
|
|||||||
* audio to the stream during this call; if needed, the request that triggered
|
* audio to the stream during this call; if needed, the request that triggered
|
||||||
* this callback will obtain the new data immediately.
|
* this callback will obtain the new data immediately.
|
||||||
*
|
*
|
||||||
* The callback's `approx_request` argument is roughly how many bytes of
|
* The callback's `additional_amount` argument is roughly how many bytes of
|
||||||
* _unconverted_ data (in the stream's input format) is needed by the caller,
|
* _unconverted_ data (in the stream's input format) is needed by the caller,
|
||||||
* although this may overestimate a little for safety. This takes into account
|
* although this may overestimate a little for safety. This takes into account
|
||||||
* how much is already in the stream and only asks for any extra necessary to
|
* how much is already in the stream and only asks for any extra necessary to
|
||||||
@@ -1762,13 +1762,13 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamGetCallback(SDL_AudioStream *
|
|||||||
* The callback can (optionally) call SDL_GetAudioStreamData() to obtain audio
|
* The callback can (optionally) call SDL_GetAudioStreamData() to obtain audio
|
||||||
* from the stream during this call.
|
* from the stream during this call.
|
||||||
*
|
*
|
||||||
* The callback's `approx_request` argument is how many bytes of _converted_
|
* The callback's `additional_amount` argument is how many bytes of
|
||||||
* data (in the stream's output format) was provided by the caller, although
|
* _converted_ data (in the stream's output format) was provided by the
|
||||||
* this may underestimate a little for safety. This value might be less than
|
* caller, although this may underestimate a little for safety. This value
|
||||||
* what is currently available in the stream, if data was already there, and
|
* might be less than what is currently available in the stream, if data was
|
||||||
* might be less than the caller provided if the stream needs to keep a buffer
|
* already there, and might be less than the caller provided if the stream
|
||||||
* to aid in resampling. Which means the callback may be provided with zero
|
* needs to keep a buffer to aid in resampling. Which means the callback may
|
||||||
* bytes, and a different amount on each call.
|
* be provided with zero bytes, and a different amount on each call.
|
||||||
*
|
*
|
||||||
* The callback may call SDL_GetAudioStreamAvailable to see the total amount
|
* The callback may call SDL_GetAudioStreamAvailable to see the total amount
|
||||||
* currently available to read from the stream, instead of the total provided
|
* currently available to read from the stream, instead of the total provided
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+11
-11
@@ -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.
|
||||||
@@ -4145,7 +4145,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUTextureSupportsFormat(
|
|||||||
* \param device a GPU context.
|
* \param device a GPU context.
|
||||||
* \param format the texture format to check.
|
* \param format the texture format to check.
|
||||||
* \param sample_count the sample count to check.
|
* \param sample_count the sample count to check.
|
||||||
* \returns a hardware-specific version of min(preferred, possible).
|
* \returns whether the sample count is supported for this texture format.
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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.
|
||||||
*
|
*
|
||||||
@@ -3607,6 +3607,22 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
|
#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variable controlling whether SDL should call XSelectInput() to enable
|
||||||
|
* input events on X11 windows wrapped by SDL windows.
|
||||||
|
*
|
||||||
|
* The variable can be set to the following values:
|
||||||
|
*
|
||||||
|
* - "0": Don't call XSelectInput(), assuming the native window code has done
|
||||||
|
* it already.
|
||||||
|
* - "1": Call XSelectInput() to enable input events. (default)
|
||||||
|
*
|
||||||
|
* This hint should be set before creating a window.
|
||||||
|
*
|
||||||
|
* \since This hint is available since SDL 3.2.10.
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT "SDL_VIDEO_X11_EXTERNAL_WINDOW_INPUT"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint
|
* A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint
|
||||||
* should be used.
|
* should be used.
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ typedef enum SDL_PowerState
|
|||||||
* It's possible a platform can only report battery percentage or time left
|
* It's possible a platform can only report battery percentage or time left
|
||||||
* but not both.
|
* but not both.
|
||||||
*
|
*
|
||||||
|
* On some platforms, retrieving power supply details might be expensive. If
|
||||||
|
* you want to display continuous status you could call this function every
|
||||||
|
* minute or so.
|
||||||
|
*
|
||||||
* \param seconds a pointer filled in with the seconds of battery life left,
|
* \param seconds a pointer filled in with the seconds of battery life left,
|
||||||
* or NULL to ignore. This will be filled in with -1 if we
|
* or NULL to ignore. This will be filled in with -1 if we
|
||||||
* can't determine a value or there is no battery.
|
* can't determine a value or there is no battery.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -1299,8 +1299,11 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* If `size` is 0, it will be set to 1.
|
* If `size` is 0, it will be set to 1.
|
||||||
*
|
*
|
||||||
* If you want to allocate memory aligned to a specific alignment, consider
|
* If the allocation is successful, the returned pointer is guaranteed to be
|
||||||
* using SDL_aligned_alloc().
|
* aligned to either the *fundamental alignment* (`alignof(max_align_t)` in
|
||||||
|
* C11 and later) or `2 * sizeof(void *)`, whichever is smaller. Use
|
||||||
|
* SDL_aligned_alloc() if you need to allocate memory aligned to an alignment
|
||||||
|
* greater than this guarantee.
|
||||||
*
|
*
|
||||||
* \param size the size to allocate.
|
* \param size the size to allocate.
|
||||||
* \returns a pointer to the allocated memory, or NULL if allocation failed.
|
* \returns a pointer to the allocated memory, or NULL if allocation failed.
|
||||||
@@ -1323,6 +1326,10 @@ extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_malloc(size_t size);
|
|||||||
*
|
*
|
||||||
* If either of `nmemb` or `size` is 0, they will both be set to 1.
|
* If either of `nmemb` or `size` is 0, they will both be set to 1.
|
||||||
*
|
*
|
||||||
|
* If the allocation is successful, the returned pointer is guaranteed to be
|
||||||
|
* aligned to either the *fundamental alignment* (`alignof(max_align_t)` in
|
||||||
|
* C11 and later) or `2 * sizeof(void *)`, whichever is smaller.
|
||||||
|
*
|
||||||
* \param nmemb the number of elements in the array.
|
* \param nmemb the number of elements in the array.
|
||||||
* \param size the size of each element of the array.
|
* \param size the size of each element of the array.
|
||||||
* \returns a pointer to the allocated array, or NULL if allocation failed.
|
* \returns a pointer to the allocated array, or NULL if allocation failed.
|
||||||
@@ -1357,6 +1364,11 @@ extern SDL_DECLSPEC SDL_MALLOC SDL_ALLOC_SIZE2(1, 2) void * SDLCALL SDL_calloc(s
|
|||||||
* - If it returns NULL (indicating failure), then `mem` will remain valid and
|
* - If it returns NULL (indicating failure), then `mem` will remain valid and
|
||||||
* must still be freed with SDL_free().
|
* must still be freed with SDL_free().
|
||||||
*
|
*
|
||||||
|
* If the allocation is successfully resized, the returned pointer is
|
||||||
|
* guaranteed to be aligned to either the *fundamental alignment*
|
||||||
|
* (`alignof(max_align_t)` in C11 and later) or `2 * sizeof(void *)`,
|
||||||
|
* whichever is smaller.
|
||||||
|
*
|
||||||
* \param mem a pointer to allocated memory to reallocate, or NULL.
|
* \param mem a pointer to allocated memory to reallocate, or NULL.
|
||||||
* \param size the new size of the memory.
|
* \param size the new size of the memory.
|
||||||
* \returns a pointer to the newly allocated memory, or NULL if allocation
|
* \returns a pointer to the newly allocated memory, or NULL if allocation
|
||||||
@@ -5962,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) */
|
||||||
|
|||||||
+127
-27
@@ -82,6 +82,7 @@ typedef Uint32 SDL_SurfaceFlags;
|
|||||||
*/
|
*/
|
||||||
typedef enum SDL_ScaleMode
|
typedef enum SDL_ScaleMode
|
||||||
{
|
{
|
||||||
|
SDL_SCALEMODE_INVALID = -1,
|
||||||
SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */
|
SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */
|
||||||
SDL_SCALEMODE_LINEAR /**< linear filtering */
|
SDL_SCALEMODE_LINEAR /**< linear filtering */
|
||||||
} SDL_ScaleMode;
|
} SDL_ScaleMode;
|
||||||
@@ -156,6 +157,8 @@ typedef struct SDL_Surface SDL_Surface;
|
|||||||
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
||||||
* call SDL_GetError() for more information.
|
* call SDL_GetError() for more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_CreateSurfaceFrom
|
* \sa SDL_CreateSurfaceFrom
|
||||||
@@ -184,6 +187,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurface(int width, int heigh
|
|||||||
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
||||||
* call SDL_GetError() for more information.
|
* call SDL_GetError() for more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_CreateSurface
|
* \sa SDL_CreateSurface
|
||||||
@@ -198,6 +203,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurfaceFrom(int width, int h
|
|||||||
*
|
*
|
||||||
* \param surface the SDL_Surface to free.
|
* \param surface the SDL_Surface to free.
|
||||||
*
|
*
|
||||||
|
* \threadsafety No other thread should be using the surface when it is freed.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_CreateSurface
|
* \sa SDL_CreateSurface
|
||||||
@@ -233,6 +240,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
|
|||||||
* \returns a valid property ID on success or 0 on failure; call
|
* \returns a valid property ID on success or 0 on failure; call
|
||||||
* SDL_GetError() for more information.
|
* SDL_GetError() for more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface);
|
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface);
|
||||||
@@ -255,6 +264,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceColorspace
|
* \sa SDL_GetSurfaceColorspace
|
||||||
@@ -272,6 +283,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface,
|
|||||||
* \returns the colorspace used by the surface, or SDL_COLORSPACE_UNKNOWN if
|
* \returns the colorspace used by the surface, or SDL_COLORSPACE_UNKNOWN if
|
||||||
* the surface is NULL.
|
* the surface is NULL.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetSurfaceColorspace
|
* \sa SDL_SetSurfaceColorspace
|
||||||
@@ -300,6 +313,8 @@ extern SDL_DECLSPEC SDL_Colorspace SDLCALL SDL_GetSurfaceColorspace(SDL_Surface
|
|||||||
* the surface didn't have an index format); call SDL_GetError() for
|
* the surface didn't have an index format); call SDL_GetError() for
|
||||||
* more information.
|
* more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetPaletteColors
|
* \sa SDL_SetPaletteColors
|
||||||
@@ -316,6 +331,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_CreateSurfacePalette(SDL_Surface *
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_CreatePalette
|
* \sa SDL_CreatePalette
|
||||||
@@ -330,6 +347,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, SDL
|
|||||||
* \returns a pointer to the palette used by the surface, or NULL if there is
|
* \returns a pointer to the palette used by the surface, or NULL if there is
|
||||||
* no palette used.
|
* no palette used.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetSurfacePalette
|
* \sa SDL_SetSurfacePalette
|
||||||
@@ -353,6 +372,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_GetSurfacePalette(SDL_Surface *sur
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_RemoveSurfaceAlternateImages
|
* \sa SDL_RemoveSurfaceAlternateImages
|
||||||
@@ -367,6 +388,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_AddSurfaceAlternateImage(SDL_Surface *surfa
|
|||||||
* \param surface the SDL_Surface structure to query.
|
* \param surface the SDL_Surface structure to query.
|
||||||
* \returns true if alternate versions are available or false otherwise.
|
* \returns true if alternate versions are available or false otherwise.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_AddSurfaceAlternateImage
|
* \sa SDL_AddSurfaceAlternateImage
|
||||||
@@ -392,6 +415,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasAlternateImages(SDL_Surface *surf
|
|||||||
* failure; call SDL_GetError() for more information. This should be
|
* failure; call SDL_GetError() for more information. This should be
|
||||||
* freed with SDL_free() when it is no longer needed.
|
* freed with SDL_free() when it is no longer needed.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_AddSurfaceAlternateImage
|
* \sa SDL_AddSurfaceAlternateImage
|
||||||
@@ -408,6 +433,8 @@ extern SDL_DECLSPEC SDL_Surface ** SDLCALL SDL_GetSurfaceImages(SDL_Surface *sur
|
|||||||
*
|
*
|
||||||
* \param surface the SDL_Surface structure to update.
|
* \param surface the SDL_Surface structure to update.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_AddSurfaceAlternateImage
|
* \sa SDL_AddSurfaceAlternateImage
|
||||||
@@ -432,6 +459,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_RemoveSurfaceAlternateImages(SDL_Surface *s
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe. The locking referred to by
|
||||||
|
* this function is making the pixels available for direct
|
||||||
|
* access, not thread-safe locking.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_MUSTLOCK
|
* \sa SDL_MUSTLOCK
|
||||||
@@ -444,6 +475,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface);
|
|||||||
*
|
*
|
||||||
* \param surface the SDL_Surface structure to be unlocked.
|
* \param surface the SDL_Surface structure to be unlocked.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe. The locking referred to by
|
||||||
|
* this function is making the pixels available for direct
|
||||||
|
* access, not thread-safe locking.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_LockSurface
|
* \sa SDL_LockSurface
|
||||||
@@ -462,6 +497,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
|
|||||||
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
|
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
|
||||||
* SDL_GetError() for more information.
|
* SDL_GetError() for more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_DestroySurface
|
* \sa SDL_DestroySurface
|
||||||
@@ -480,6 +517,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, bool
|
|||||||
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
|
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
|
||||||
* SDL_GetError() for more information.
|
* SDL_GetError() for more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_DestroySurface
|
* \sa SDL_DestroySurface
|
||||||
@@ -504,6 +543,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file);
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_LoadBMP_IO
|
* \sa SDL_LoadBMP_IO
|
||||||
@@ -525,6 +566,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStre
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_LoadBMP
|
* \sa SDL_LoadBMP
|
||||||
@@ -543,6 +586,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *f
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_BlitSurface
|
* \sa SDL_BlitSurface
|
||||||
@@ -559,6 +604,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, bool en
|
|||||||
* \param surface the SDL_Surface structure to query.
|
* \param surface the SDL_Surface structure to query.
|
||||||
* \returns true if the surface is RLE enabled, false otherwise.
|
* \returns true if the surface is RLE enabled, false otherwise.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetSurfaceRLE
|
* \sa SDL_SetSurfaceRLE
|
||||||
@@ -581,6 +628,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface);
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceColorKey
|
* \sa SDL_GetSurfaceColorKey
|
||||||
@@ -597,6 +646,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorKey(SDL_Surface *surface, bo
|
|||||||
* \param surface the SDL_Surface structure to query.
|
* \param surface the SDL_Surface structure to query.
|
||||||
* \returns true if the surface has a color key, false otherwise.
|
* \returns true if the surface has a color key, false otherwise.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetSurfaceColorKey
|
* \sa SDL_SetSurfaceColorKey
|
||||||
@@ -617,6 +668,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasColorKey(SDL_Surface *surface);
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetSurfaceColorKey
|
* \sa SDL_SetSurfaceColorKey
|
||||||
@@ -640,6 +693,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Ui
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceColorMod
|
* \sa SDL_GetSurfaceColorMod
|
||||||
@@ -658,6 +713,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, Ui
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceAlphaMod
|
* \sa SDL_GetSurfaceAlphaMod
|
||||||
@@ -678,6 +735,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Ui
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceAlphaMod
|
* \sa SDL_GetSurfaceAlphaMod
|
||||||
@@ -693,6 +752,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Ui
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceColorMod
|
* \sa SDL_GetSurfaceColorMod
|
||||||
@@ -712,6 +773,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Ui
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceBlendMode
|
* \sa SDL_GetSurfaceBlendMode
|
||||||
@@ -726,6 +789,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, S
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetSurfaceBlendMode
|
* \sa SDL_SetSurfaceBlendMode
|
||||||
@@ -747,6 +812,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, S
|
|||||||
* \returns true if the rectangle intersects the surface, otherwise false and
|
* \returns true if the rectangle intersects the surface, otherwise false and
|
||||||
* blits will be completely clipped.
|
* blits will be completely clipped.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_GetSurfaceClipRect
|
* \sa SDL_GetSurfaceClipRect
|
||||||
@@ -766,6 +833,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, co
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_SetSurfaceClipRect
|
* \sa SDL_SetSurfaceClipRect
|
||||||
@@ -780,6 +849,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, SD
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip);
|
extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip);
|
||||||
@@ -796,6 +867,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipM
|
|||||||
* \returns a copy of the surface or NULL on failure; call SDL_GetError() for
|
* \returns a copy of the surface or NULL on failure; call SDL_GetError() for
|
||||||
* more information.
|
* more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_DestroySurface
|
* \sa SDL_DestroySurface
|
||||||
@@ -815,6 +888,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_DuplicateSurface(SDL_Surface *surf
|
|||||||
* \returns a copy of the surface or NULL on failure; call SDL_GetError() for
|
* \returns a copy of the surface or NULL on failure; call SDL_GetError() for
|
||||||
* more information.
|
* more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_DestroySurface
|
* \sa SDL_DestroySurface
|
||||||
@@ -840,6 +915,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ScaleSurface(SDL_Surface *surface,
|
|||||||
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
||||||
* call SDL_GetError() for more information.
|
* call SDL_GetError() for more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_ConvertSurfaceAndColorspace
|
* \sa SDL_ConvertSurfaceAndColorspace
|
||||||
@@ -866,6 +943,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurface(SDL_Surface *surfac
|
|||||||
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
* \returns the new SDL_Surface structure that is created or NULL on failure;
|
||||||
* call SDL_GetError() for more information.
|
* call SDL_GetError() for more information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_ConvertSurface
|
* \sa SDL_ConvertSurface
|
||||||
@@ -887,6 +966,10 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurfaceAndColorspace(SDL_Su
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety The same destination pixels should not be used from two
|
||||||
|
* threads at once. It is safe to use the same source pixels
|
||||||
|
* from multiple threads.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_ConvertPixelsAndColorspace
|
* \sa SDL_ConvertPixelsAndColorspace
|
||||||
@@ -916,6 +999,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixels(int width, int height, SDL_Pi
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety The same destination pixels should not be used from two
|
||||||
|
* threads at once. It is safe to use the same source pixels
|
||||||
|
* from multiple threads.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_ConvertPixels
|
* \sa SDL_ConvertPixels
|
||||||
@@ -940,6 +1027,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixelsAndColorspace(int width, int h
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety The same destination pixels should not be used from two
|
||||||
|
* threads at once. It is safe to use the same source pixels
|
||||||
|
* from multiple threads.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_PixelFormat src_format, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, bool linear);
|
extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_PixelFormat src_format, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, bool linear);
|
||||||
@@ -955,6 +1046,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surface, bool linear);
|
extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surface, bool linear);
|
||||||
@@ -975,6 +1068,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surfac
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, float g, float b, float a);
|
extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, float g, float b, float a);
|
||||||
@@ -998,6 +1093,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r,
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_FillSurfaceRects
|
* \sa SDL_FillSurfaceRects
|
||||||
@@ -1023,6 +1120,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRect(SDL_Surface *dst, const SDL
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_FillSurfaceRect
|
* \sa SDL_FillSurfaceRect
|
||||||
@@ -1036,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
|
||||||
@@ -1096,9 +1192,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SD
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
@@ -1121,9 +1216,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rec
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
@@ -1146,9 +1240,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUnchecked(SDL_Surface *src, cons
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
@@ -1172,9 +1265,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const S
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
@@ -1195,9 +1287,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.4.0.
|
* \since This function is available since SDL 3.4.0.
|
||||||
*
|
*
|
||||||
@@ -1221,9 +1312,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_StretchSurface(SDL_Surface *src, const SDL_
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
@@ -1251,9 +1341,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiled(SDL_Surface *src, const SD
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
@@ -1288,9 +1377,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiledWithScale(SDL_Surface *src,
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* \threadsafety The same destination surface should not be used from two
|
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
|
||||||
* threads at once. It is safe to use the same source surface
|
* at any given time.
|
||||||
* from multiple threads.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
@@ -1322,6 +1410,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface9Grid(SDL_Surface *src, const SD
|
|||||||
* \param b the blue component of the pixel in the range 0-255.
|
* \param b the blue component of the pixel in the range 0-255.
|
||||||
* \returns a pixel value.
|
* \returns a pixel value.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_MapSurfaceRGBA
|
* \sa SDL_MapSurfaceRGBA
|
||||||
@@ -1353,6 +1443,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGB(SDL_Surface *surface, Uint8
|
|||||||
* \param a the alpha component of the pixel in the range 0-255.
|
* \param a the alpha component of the pixel in the range 0-255.
|
||||||
* \returns a pixel value.
|
* \returns a pixel value.
|
||||||
*
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_MapSurfaceRGB
|
* \sa SDL_MapSurfaceRGB
|
||||||
@@ -1382,6 +1474,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
|
extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
|
||||||
@@ -1406,6 +1500,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, int x, int y, float *r, float *g, float *b, float *a);
|
extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, int x, int y, float *r, float *g, float *b, float *a);
|
||||||
@@ -1429,6 +1525,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface,
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||||
@@ -1449,6 +1547,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int
|
|||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
|
* \threadsafety This function is not thread safe.
|
||||||
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixelFloat(SDL_Surface *surface, int x, int y, float r, float g, float b, float a);
|
extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixelFloat(SDL_Surface *surface, int x, int y, float r, float g, float b, float a);
|
||||||
|
|||||||
@@ -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 6
|
#define SDL_MICRO_VERSION 14
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
|||||||
@@ -356,7 +356,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
|||||||
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
|
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||||
if (!SDL_VideoInit(NULL)) {
|
if (!SDL_VideoInit(NULL)) {
|
||||||
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
|
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||||
|
SDL_PushError();
|
||||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||||
|
SDL_PopError();
|
||||||
goto quit_and_error;
|
goto quit_and_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -381,7 +383,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
|||||||
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
|
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
|
||||||
if (!SDL_InitAudio(NULL)) {
|
if (!SDL_InitAudio(NULL)) {
|
||||||
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
|
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
|
||||||
|
SDL_PushError();
|
||||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||||
|
SDL_PopError();
|
||||||
goto quit_and_error;
|
goto quit_and_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -406,7 +410,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
|||||||
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
|
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
|
||||||
if (!SDL_InitJoysticks()) {
|
if (!SDL_InitJoysticks()) {
|
||||||
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
|
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
|
||||||
|
SDL_PushError();
|
||||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||||
|
SDL_PopError();
|
||||||
goto quit_and_error;
|
goto quit_and_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -430,7 +436,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
|||||||
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
|
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
|
||||||
if (!SDL_InitGamepads()) {
|
if (!SDL_InitGamepads()) {
|
||||||
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
|
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
|
||||||
|
SDL_PushError();
|
||||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
SDL_PopError();
|
||||||
goto quit_and_error;
|
goto quit_and_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -493,7 +501,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
|||||||
SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA);
|
SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA);
|
||||||
if (!SDL_CameraInit(NULL)) {
|
if (!SDL_CameraInit(NULL)) {
|
||||||
SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA);
|
SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA);
|
||||||
|
SDL_PushError();
|
||||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||||
|
SDL_PopError();
|
||||||
goto quit_and_error;
|
goto quit_and_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -511,7 +521,11 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
|||||||
return SDL_ClearError();
|
return SDL_ClearError();
|
||||||
|
|
||||||
quit_and_error:
|
quit_and_error:
|
||||||
SDL_QuitSubSystem(flags_initialized);
|
{
|
||||||
|
SDL_PushError();
|
||||||
|
SDL_QuitSubSystem(flags_initialized);
|
||||||
|
SDL_PopError();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-18
@@ -34,15 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_PLATFORM_EMSCRIPTEN
|
#ifdef SDL_PLATFORM_EMSCRIPTEN
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
// older Emscriptens don't have this, but we need to for wasm64 compatibility.
|
|
||||||
#ifndef MAIN_THREAD_EM_ASM_PTR
|
|
||||||
#ifdef __wasm64__
|
|
||||||
#error You need to upgrade your Emscripten compiler to support wasm64
|
|
||||||
#else
|
|
||||||
#define MAIN_THREAD_EM_ASM_PTR MAIN_THREAD_EM_ASM_INT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The size of the stack buffer to use for rendering assert messages.
|
// The size of the stack buffer to use for rendering assert messages.
|
||||||
@@ -252,7 +244,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
bool okay = true;
|
bool okay = true;
|
||||||
/* *INDENT-OFF* */ // clang-format off
|
/* *INDENT-OFF* */ // clang-format off
|
||||||
char *buf = (char *) MAIN_THREAD_EM_ASM_PTR({
|
int reply = MAIN_THREAD_EM_ASM_INT({
|
||||||
var str =
|
var str =
|
||||||
UTF8ToString($0) + '\n\n' +
|
UTF8ToString($0) + '\n\n' +
|
||||||
'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';
|
'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';
|
||||||
@@ -260,26 +252,32 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
|
|||||||
if (reply === null) {
|
if (reply === null) {
|
||||||
reply = "i";
|
reply = "i";
|
||||||
}
|
}
|
||||||
return allocate(intArrayFromString(reply), 'i8', ALLOC_NORMAL);
|
return reply.length === 1 ? reply.charCodeAt(0) : -1;
|
||||||
}, message);
|
}, message);
|
||||||
/* *INDENT-ON* */ // clang-format on
|
/* *INDENT-ON* */ // clang-format on
|
||||||
|
|
||||||
if (SDL_strcmp(buf, "a") == 0) {
|
switch (reply) {
|
||||||
|
case 'a':
|
||||||
state = SDL_ASSERTION_ABORT;
|
state = SDL_ASSERTION_ABORT;
|
||||||
|
break;
|
||||||
#if 0 // (currently) no break functionality on Emscripten
|
#if 0 // (currently) no break functionality on Emscripten
|
||||||
} else if (SDL_strcmp(buf, "b") == 0) {
|
case 'b':
|
||||||
state = SDL_ASSERTION_BREAK;
|
state = SDL_ASSERTION_BREAK;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
} else if (SDL_strcmp(buf, "r") == 0) {
|
case 'r':
|
||||||
state = SDL_ASSERTION_RETRY;
|
state = SDL_ASSERTION_RETRY;
|
||||||
} else if (SDL_strcmp(buf, "i") == 0) {
|
break;
|
||||||
|
case 'i':
|
||||||
state = SDL_ASSERTION_IGNORE;
|
state = SDL_ASSERTION_IGNORE;
|
||||||
} else if (SDL_strcmp(buf, "A") == 0) {
|
break;
|
||||||
|
case 'A':
|
||||||
state = SDL_ASSERTION_ALWAYS_IGNORE;
|
state = SDL_ASSERTION_ALWAYS_IGNORE;
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
okay = false;
|
okay = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
free(buf); // This should NOT be SDL_free()
|
|
||||||
|
|
||||||
if (okay) {
|
if (okay) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -46,4 +46,16 @@ typedef struct SDL_error
|
|||||||
// Defined in SDL_thread.c
|
// Defined in SDL_thread.c
|
||||||
extern SDL_error *SDL_GetErrBuf(bool create);
|
extern SDL_error *SDL_GetErrBuf(bool create);
|
||||||
|
|
||||||
|
// Macros to save and restore error values
|
||||||
|
#define SDL_PushError() \
|
||||||
|
char *saved_error = SDL_strdup(SDL_GetError())
|
||||||
|
|
||||||
|
#define SDL_PopError() \
|
||||||
|
do { \
|
||||||
|
if (saved_error) { \
|
||||||
|
SDL_SetError("%s", saved_error); \
|
||||||
|
SDL_free(saved_error); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif // SDL_error_c_h_
|
#endif // SDL_error_c_h_
|
||||||
@@ -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 ", "" },
|
||||||
|
|||||||
+35
-7
@@ -410,6 +410,7 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid,
|
|||||||
SDL_LockRWLockForReading(current_audio.device_hash_lock);
|
SDL_LockRWLockForReading(current_audio.device_hash_lock);
|
||||||
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev);
|
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev);
|
||||||
if (logdev) {
|
if (logdev) {
|
||||||
|
SDL_assert(logdev->instance_id == devid);
|
||||||
device = logdev->physical_device;
|
device = logdev->physical_device;
|
||||||
SDL_assert(device != NULL);
|
SDL_assert(device != NULL);
|
||||||
RefPhysicalAudioDevice(device); // reference it, in case the logical device migrates to a new default.
|
RefPhysicalAudioDevice(device); // reference it, in case the logical device migrates to a new default.
|
||||||
@@ -459,6 +460,7 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // !
|
|||||||
} else {
|
} else {
|
||||||
SDL_LockRWLockForReading(current_audio.device_hash_lock);
|
SDL_LockRWLockForReading(current_audio.device_hash_lock);
|
||||||
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device);
|
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device);
|
||||||
|
SDL_assert(device->instance_id == devid);
|
||||||
SDL_UnlockRWLock(current_audio.device_hash_lock);
|
SDL_UnlockRWLock(current_audio.device_hash_lock);
|
||||||
|
|
||||||
if (!device) {
|
if (!device) {
|
||||||
@@ -883,6 +885,7 @@ static bool SDLCALL FindLowestDeviceID(void *userdata, const SDL_HashTable *tabl
|
|||||||
if (isphysical && (devid_recording == data->recording) && (devid < data->highest)) {
|
if (isphysical && (devid_recording == data->recording) && (devid < data->highest)) {
|
||||||
data->highest = devid;
|
data->highest = devid;
|
||||||
data->result = (SDL_AudioDevice *) value;
|
data->result = (SDL_AudioDevice *) value;
|
||||||
|
SDL_assert(data->result->instance_id == devid);
|
||||||
}
|
}
|
||||||
return true; // keep iterating.
|
return true; // keep iterating.
|
||||||
}
|
}
|
||||||
@@ -1051,7 +1054,10 @@ static bool SDLCALL DestroyOnePhysicalAudioDevice(void *userdata, const SDL_Hash
|
|||||||
const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key;
|
const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key;
|
||||||
const bool isphysical = !!(devid & (1<<1));
|
const bool isphysical = !!(devid & (1<<1));
|
||||||
if (isphysical) {
|
if (isphysical) {
|
||||||
DestroyPhysicalAudioDevice((SDL_AudioDevice *) value);
|
SDL_AudioDevice *dev = (SDL_AudioDevice *) value;
|
||||||
|
|
||||||
|
SDL_assert(dev->instance_id == devid);
|
||||||
|
DestroyPhysicalAudioDevice(dev);
|
||||||
}
|
}
|
||||||
return true; // keep iterating.
|
return true; // keep iterating.
|
||||||
}
|
}
|
||||||
@@ -1256,11 +1262,11 @@ static int SDLCALL PlaybackAudioThread(void *devicep) // thread entry point
|
|||||||
SDL_assert(!device->recording);
|
SDL_assert(!device->recording);
|
||||||
SDL_PlaybackAudioThreadSetup(device);
|
SDL_PlaybackAudioThreadSetup(device);
|
||||||
|
|
||||||
do {
|
while (SDL_PlaybackAudioThreadIterate(device)) {
|
||||||
if (!device->WaitDevice(device)) {
|
if (!device->WaitDevice(device)) {
|
||||||
SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!)
|
SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!)
|
||||||
}
|
}
|
||||||
} while (SDL_PlaybackAudioThreadIterate(device));
|
}
|
||||||
|
|
||||||
SDL_PlaybackAudioThreadShutdown(device);
|
SDL_PlaybackAudioThreadShutdown(device);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1464,6 +1470,7 @@ static bool SDLCALL FindAudioDeviceByCallback(void *userdata, const SDL_HashTabl
|
|||||||
SDL_AudioDevice *device = (SDL_AudioDevice *) value;
|
SDL_AudioDevice *device = (SDL_AudioDevice *) value;
|
||||||
if (data->callback(device, data->userdata)) { // found it?
|
if (data->callback(device, data->userdata)) { // found it?
|
||||||
data->retval = device;
|
data->retval = device;
|
||||||
|
SDL_assert(data->retval->instance_id == devid);
|
||||||
return false; // stop iterating, we found it.
|
return false; // stop iterating, we found it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1502,12 +1509,33 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle)
|
|||||||
|
|
||||||
const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
|
const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
|
||||||
{
|
{
|
||||||
|
// bit #1 of devid is set for physical devices and unset for logical.
|
||||||
|
const bool islogical = !(devid & (1<<1));
|
||||||
const char *result = NULL;
|
const char *result = NULL;
|
||||||
SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid);
|
const void *vdev = 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, &vdev);
|
||||||
|
if (!vdev) {
|
||||||
|
SDL_SetError("Invalid audio device instance ID");
|
||||||
|
} else if (islogical) {
|
||||||
|
const SDL_LogicalAudioDevice *logdev = (const SDL_LogicalAudioDevice *) vdev;
|
||||||
|
SDL_assert(logdev->instance_id == devid);
|
||||||
|
result = SDL_GetPersistentString(logdev->physical_device->name);
|
||||||
|
} else {
|
||||||
|
const SDL_AudioDevice *device = (const SDL_AudioDevice *) vdev;
|
||||||
|
SDL_assert(device->instance_id == devid);
|
||||||
|
result = SDL_GetPersistentString(device->name);
|
||||||
|
}
|
||||||
|
SDL_UnlockRWLock(current_audio.device_hash_lock);
|
||||||
}
|
}
|
||||||
ReleaseAudioDevice(device);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
|
|
||||||
#include "SDL_sysaudio.h"
|
#include "SDL_sysaudio.h"
|
||||||
|
|
||||||
|
#ifdef SDL_NEON_INTRINSICS
|
||||||
|
#include <fenv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DIVBY2147483648 0.0000000004656612873077392578125f // 0x1p-31f
|
#define DIVBY2147483648 0.0000000004656612873077392578125f // 0x1p-31f
|
||||||
|
|
||||||
// start fallback scalar converters
|
// start fallback scalar converters
|
||||||
@@ -527,9 +531,27 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32* dst, const U
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_NEON_INTRINSICS
|
#ifdef SDL_NEON_INTRINSICS
|
||||||
|
|
||||||
|
// C99 requires that all code modifying floating point environment should
|
||||||
|
// be guarded by the STDC FENV_ACCESS pragma; otherwise, it's undefined
|
||||||
|
// behavior. However, the compiler support for this pragma is bad.
|
||||||
|
#if defined(__clang__)
|
||||||
|
#if __clang_major__ >= 12
|
||||||
|
#pragma STDC FENV_ACCESS ON
|
||||||
|
#endif
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#pragma fenv_access (on)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
// GCC does not support the pragma at all
|
||||||
|
#else
|
||||||
|
#pragma STDC FENV_ACCESS ON
|
||||||
|
#endif
|
||||||
|
|
||||||
static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_samples)
|
static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("S8", "F32 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("S8", "F32 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
CONVERT_16_REV({
|
CONVERT_16_REV({
|
||||||
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 7), 0);
|
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 7), 0);
|
||||||
@@ -549,11 +571,14 @@ static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_sam
|
|||||||
vst1q_f32(&dst[i + 8], floats2);
|
vst1q_f32(&dst[i + 8], floats2);
|
||||||
vst1q_f32(&dst[i + 12], floats3);
|
vst1q_f32(&dst[i + 12], floats3);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_samples)
|
static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("U8", "F32 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("U8", "F32 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
uint8x16_t flipper = vdupq_n_u8(0x80);
|
uint8x16_t flipper = vdupq_n_u8(0x80);
|
||||||
|
|
||||||
@@ -575,11 +600,14 @@ static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_sam
|
|||||||
vst1q_f32(&dst[i + 8], floats2);
|
vst1q_f32(&dst[i + 8], floats2);
|
||||||
vst1q_f32(&dst[i + 12], floats3);
|
vst1q_f32(&dst[i + 12], floats3);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_samples)
|
static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("S16", "F32 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("S16", "F32 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
CONVERT_16_REV({
|
CONVERT_16_REV({
|
||||||
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 15), 0);
|
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 15), 0);
|
||||||
@@ -597,11 +625,14 @@ static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_s
|
|||||||
vst1q_f32(&dst[i + 8], floats2);
|
vst1q_f32(&dst[i + 8], floats2);
|
||||||
vst1q_f32(&dst[i + 12], floats3);
|
vst1q_f32(&dst[i + 12], floats3);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_samples)
|
static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
CONVERT_16_FWD({
|
CONVERT_16_FWD({
|
||||||
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vld1_dup_s32(&src[i]), 31), 0);
|
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vld1_dup_s32(&src[i]), 31), 0);
|
||||||
@@ -621,11 +652,14 @@ static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_s
|
|||||||
vst1q_f32(&dst[i + 8], floats2);
|
vst1q_f32(&dst[i + 8], floats2);
|
||||||
vst1q_f32(&dst[i + 12], floats3);
|
vst1q_f32(&dst[i + 12], floats3);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_samples)
|
static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("F32", "S8 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("F32", "S8 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
CONVERT_16_FWD({
|
CONVERT_16_FWD({
|
||||||
vst1_lane_s8(&dst[i], vreinterpret_s8_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 3);
|
vst1_lane_s8(&dst[i], vreinterpret_s8_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 3);
|
||||||
@@ -647,11 +681,14 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam
|
|||||||
|
|
||||||
vst1q_s8(&dst[i], bytes);
|
vst1q_s8(&dst[i], bytes);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_samples)
|
static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("F32", "U8 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("F32", "U8 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
uint8x16_t flipper = vdupq_n_u8(0x80);
|
uint8x16_t flipper = vdupq_n_u8(0x80);
|
||||||
|
|
||||||
@@ -679,11 +716,14 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam
|
|||||||
|
|
||||||
vst1q_u8(&dst[i], bytes);
|
vst1q_u8(&dst[i], bytes);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_samples)
|
static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("F32", "S16 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("F32", "S16 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
CONVERT_16_FWD({
|
CONVERT_16_FWD({
|
||||||
vst1_lane_s16(&dst[i], vreinterpret_s16_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 1);
|
vst1_lane_s16(&dst[i], vreinterpret_s16_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 1);
|
||||||
@@ -704,11 +744,14 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s
|
|||||||
vst1q_s16(&dst[i], shorts0);
|
vst1q_s16(&dst[i], shorts0);
|
||||||
vst1q_s16(&dst[i + 8], shorts1);
|
vst1q_s16(&dst[i + 8], shorts1);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_samples)
|
static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_samples)
|
||||||
{
|
{
|
||||||
LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using NEON)");
|
LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using NEON)");
|
||||||
|
fenv_t fenv;
|
||||||
|
feholdexcept(&fenv);
|
||||||
|
|
||||||
CONVERT_16_FWD({
|
CONVERT_16_FWD({
|
||||||
vst1_lane_s32(&dst[i], vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31), 0);
|
vst1_lane_s32(&dst[i], vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31), 0);
|
||||||
@@ -728,6 +771,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s
|
|||||||
vst1q_s32(&dst[i + 8], ints2);
|
vst1q_s32(&dst[i + 8], ints2);
|
||||||
vst1q_s32(&dst[i + 12], ints3);
|
vst1q_s32(&dst[i + 12], ints3);
|
||||||
})
|
})
|
||||||
|
fesetenv(&fenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_Convert_Swap16_NEON(Uint16* dst, const Uint16* src, int num_samples)
|
static void SDL_Convert_Swap16_NEON(Uint16* dst, const Uint16* src, int num_samples)
|
||||||
@@ -767,6 +811,19 @@ static void SDL_Convert_Swap32_NEON(Uint32* dst, const Uint32* src, int num_samp
|
|||||||
vst1q_u8((Uint8*)&dst[i + 12], ints3);
|
vst1q_u8((Uint8*)&dst[i + 12], ints3);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#if __clang_major__ >= 12
|
||||||
|
#pragma STDC FENV_ACCESS DEFAULT
|
||||||
|
#endif
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#pragma fenv_access (off)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
//
|
||||||
|
#else
|
||||||
|
#pragma STDC FENV_ACCESS DEFAULT
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef CONVERT_16_FWD
|
#undef CONVERT_16_FWD
|
||||||
|
|||||||
@@ -308,6 +308,12 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
|
|||||||
ctx.AAudioStreamBuilder_setFormat(builder, format);
|
ctx.AAudioStreamBuilder_setFormat(builder, format);
|
||||||
ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq);
|
ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq);
|
||||||
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
|
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
|
||||||
|
|
||||||
|
// If no specific buffer size has been requested, the device will pick the optimal
|
||||||
|
if(SDL_GetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES)) {
|
||||||
|
ctx.AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2 * device->sample_frames); // AAudio requires that the buffer capacity is at least
|
||||||
|
ctx.AAudioStreamBuilder_setFramesPerDataCallback(builder, device->sample_frames); // twice the size of the data callback buffer size
|
||||||
|
}
|
||||||
|
|
||||||
const aaudio_direction_t direction = (recording ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
|
const aaudio_direction_t direction = (recording ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
|
||||||
ctx.AAudioStreamBuilder_setDirection(builder, direction);
|
ctx.AAudioStreamBuilder_setDirection(builder, direction);
|
||||||
@@ -366,7 +372,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;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSamplesPerFrame, (AAudioStreamBuild
|
|||||||
SDL_PROC(void, AAudioStreamBuilder_setFormat, (AAudioStreamBuilder * builder, aaudio_format_t format))
|
SDL_PROC(void, AAudioStreamBuilder_setFormat, (AAudioStreamBuilder * builder, aaudio_format_t format))
|
||||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSharingMode, (AAudioStreamBuilder * builder, aaudio_sharing_mode_t sharingMode))
|
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSharingMode, (AAudioStreamBuilder * builder, aaudio_sharing_mode_t sharingMode))
|
||||||
SDL_PROC(void, AAudioStreamBuilder_setDirection, (AAudioStreamBuilder * builder, aaudio_direction_t direction))
|
SDL_PROC(void, AAudioStreamBuilder_setDirection, (AAudioStreamBuilder * builder, aaudio_direction_t direction))
|
||||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames))
|
SDL_PROC(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames))
|
||||||
SDL_PROC(void, AAudioStreamBuilder_setPerformanceMode, (AAudioStreamBuilder * builder, aaudio_performance_mode_t mode))
|
SDL_PROC(void, AAudioStreamBuilder_setPerformanceMode, (AAudioStreamBuilder * builder, aaudio_performance_mode_t mode))
|
||||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) // API 28
|
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) // API 28
|
||||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) // API 28
|
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) // API 28
|
||||||
|
|||||||
@@ -1187,7 +1187,6 @@ static bool ALSA_OpenDevice(SDL_AudioDevice *device)
|
|||||||
ALSA_snd_pcm_nonblock(cfg_ctx.device->hidden->pcm, 0);
|
ALSA_snd_pcm_nonblock(cfg_ctx.device->hidden->pcm, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ALSA_snd_pcm_start(cfg_ctx.device->hidden->pcm);
|
|
||||||
return true; // We're ready to rock and roll. :-)
|
return true; // We're ready to rock and roll. :-)
|
||||||
|
|
||||||
err_cleanup_ctx:
|
err_cleanup_ctx:
|
||||||
@@ -1200,6 +1199,13 @@ err_free_device_hidden:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ALSA_ThreadInit(SDL_AudioDevice *device)
|
||||||
|
{
|
||||||
|
SDL_SetCurrentThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL);
|
||||||
|
// do snd_pcm_start as close to the first time we PlayDevice as possible to prevent an underrun at startup.
|
||||||
|
ALSA_snd_pcm_start(device->hidden->pcm);
|
||||||
|
}
|
||||||
|
|
||||||
static ALSA_Device *hotplug_devices = NULL;
|
static ALSA_Device *hotplug_devices = NULL;
|
||||||
|
|
||||||
static int hotplug_device_process(snd_ctl_t *ctl, snd_ctl_card_info_t *ctl_card_info, int dev_idx,
|
static int hotplug_device_process(snd_ctl_t *ctl, snd_ctl_card_info_t *ctl_card_info, int dev_idx,
|
||||||
@@ -1497,6 +1503,7 @@ static bool ALSA_Init(SDL_AudioDriverImpl *impl)
|
|||||||
|
|
||||||
impl->DetectDevices = ALSA_DetectDevices;
|
impl->DetectDevices = ALSA_DetectDevices;
|
||||||
impl->OpenDevice = ALSA_OpenDevice;
|
impl->OpenDevice = ALSA_OpenDevice;
|
||||||
|
impl->ThreadInit = ALSA_ThreadInit;
|
||||||
impl->WaitDevice = ALSA_WaitDevice;
|
impl->WaitDevice = ALSA_WaitDevice;
|
||||||
impl->GetDeviceBuf = ALSA_GetDeviceBuf;
|
impl->GetDeviceBuf = ALSA_GetDeviceBuf;
|
||||||
impl->PlayDevice = ALSA_PlayDevice;
|
impl->PlayDevice = ALSA_PlayDevice;
|
||||||
|
|||||||
@@ -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";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1187,7 +1193,11 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
|
|||||||
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%i", device->sample_frames, device->spec.freq);
|
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%i", device->sample_frames, device->spec.freq);
|
||||||
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", device->spec.freq);
|
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", device->spec.freq);
|
||||||
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
|
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
|
||||||
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware.
|
|
||||||
|
// UPDATE: This prevents users from moving the audio to a new sink (device) using standard tools. This is slightly in conflict
|
||||||
|
// with how SDL wants to manage audio devices, but if people want to do it, we should let them, so this is commented out
|
||||||
|
// for now. We might revisit later.
|
||||||
|
//PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware.
|
||||||
|
|
||||||
if (node_id != PW_ID_ANY) {
|
if (node_id != PW_ID_ANY) {
|
||||||
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
|
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ static bool PULSEAUDIO_WaitDevice(SDL_AudioDevice *device)
|
|||||||
struct SDL_PrivateAudioData *h = device->hidden;
|
struct SDL_PrivateAudioData *h = device->hidden;
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
//SDL_Log("PULSEAUDIO PLAYDEVICE START! mixlen=%d", available);
|
//SDL_Log("PULSEAUDIO WAITDEVICE START! mixlen=%d", available);
|
||||||
|
|
||||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||||
|
|
||||||
@@ -701,7 +701,10 @@ static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
|||||||
PULSEAUDIO_pa_stream_set_state_callback(h->stream, PulseStreamStateChangeCallback, NULL);
|
PULSEAUDIO_pa_stream_set_state_callback(h->stream, PulseStreamStateChangeCallback, NULL);
|
||||||
|
|
||||||
// SDL manages device moves if the default changes, so don't ever let Pulse automatically migrate this stream.
|
// SDL manages device moves if the default changes, so don't ever let Pulse automatically migrate this stream.
|
||||||
flags |= PA_STREAM_DONT_MOVE;
|
// UPDATE: This prevents users from moving the audio to a new sink (device) using standard tools. This is slightly in conflict
|
||||||
|
// with how SDL wants to manage audio devices, but if people want to do it, we should let them, so this is commented out
|
||||||
|
// for now. We might revisit later.
|
||||||
|
//flags |= PA_STREAM_DONT_MOVE;
|
||||||
|
|
||||||
const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path;
|
const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path;
|
||||||
if (recording) {
|
if (recording) {
|
||||||
|
|||||||
@@ -130,7 +130,8 @@ static bool VITAAUD_OpenDevice(SDL_AudioDevice *device)
|
|||||||
|
|
||||||
static bool VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
|
static bool VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return (sceAudioOutOutput(device->hidden->port, buffer) == 0);
|
// sceAudioOutOutput returns amount of samples queued or < 0 on error
|
||||||
|
return (sceAudioOutOutput(device->hidden->port, buffer) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ static bool pipewire_initialized = false;
|
|||||||
|
|
||||||
// Pipewire entry points
|
// Pipewire entry points
|
||||||
static const char *(*PIPEWIRE_pw_get_library_version)(void);
|
static const char *(*PIPEWIRE_pw_get_library_version)(void);
|
||||||
|
#if PW_CHECK_VERSION(0, 3, 75)
|
||||||
static bool (*PIPEWIRE_pw_check_library_version)(int major, int minor, int micro);
|
static bool (*PIPEWIRE_pw_check_library_version)(int major, int minor, int micro);
|
||||||
|
#endif
|
||||||
static void (*PIPEWIRE_pw_init)(int *, char ***);
|
static void (*PIPEWIRE_pw_init)(int *, char ***);
|
||||||
static void (*PIPEWIRE_pw_deinit)(void);
|
static void (*PIPEWIRE_pw_deinit)(void);
|
||||||
static struct pw_main_loop *(*PIPEWIRE_pw_main_loop_new)(const struct spa_dict *loop);
|
static struct pw_main_loop *(*PIPEWIRE_pw_main_loop_new)(const struct spa_dict *loop);
|
||||||
@@ -151,7 +153,9 @@ static void unload_pipewire_library(void)
|
|||||||
static bool load_pipewire_syms(void)
|
static bool load_pipewire_syms(void)
|
||||||
{
|
{
|
||||||
SDL_PIPEWIRE_SYM(pw_get_library_version);
|
SDL_PIPEWIRE_SYM(pw_get_library_version);
|
||||||
|
#if PW_CHECK_VERSION(0, 3, 75)
|
||||||
SDL_PIPEWIRE_SYM(pw_check_library_version);
|
SDL_PIPEWIRE_SYM(pw_check_library_version);
|
||||||
|
#endif
|
||||||
SDL_PIPEWIRE_SYM(pw_init);
|
SDL_PIPEWIRE_SYM(pw_init);
|
||||||
SDL_PIPEWIRE_SYM(pw_deinit);
|
SDL_PIPEWIRE_SYM(pw_deinit);
|
||||||
SDL_PIPEWIRE_SYM(pw_main_loop_new);
|
SDL_PIPEWIRE_SYM(pw_main_loop_new);
|
||||||
@@ -1024,7 +1028,11 @@ static bool hotplug_loop_init(void)
|
|||||||
|
|
||||||
spa_list_init(&hotplug.global_list);
|
spa_list_init(&hotplug.global_list);
|
||||||
|
|
||||||
|
#if PW_CHECK_VERSION(0, 3, 75)
|
||||||
hotplug.have_1_0_5 = PIPEWIRE_pw_check_library_version(1,0,5);
|
hotplug.have_1_0_5 = PIPEWIRE_pw_check_library_version(1,0,5);
|
||||||
|
#else
|
||||||
|
hotplug.have_1_0_5 = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
hotplug.loop = PIPEWIRE_pw_thread_loop_new("SDLPwCameraPlug", NULL);
|
hotplug.loop = PIPEWIRE_pw_thread_loop_new("SDLPwCameraPlug", NULL);
|
||||||
if (!hotplug.loop) {
|
if (!hotplug.loop) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -330,10 +330,10 @@ void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect)
|
|||||||
winrect->bottom = sdlrect->y + sdlrect->h - 1;
|
winrect->bottom = sdlrect->y + sdlrect->h - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_IsRectEmpty(const RECT *rect)
|
bool WIN_WindowRectValid(const RECT *rect)
|
||||||
{
|
{
|
||||||
// Calculating this manually because Xbox does not support Win32 IsRectEmpty.
|
// A window can be resized to zero height, but not zero width
|
||||||
return (rect->right <= rect->left) || (rect->bottom <= rect->top);
|
return (rect->right > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some GUIDs we need to know without linking to libraries that aren't available before Vista.
|
// Some GUIDs we need to know without linking to libraries that aren't available before Vista.
|
||||||
|
|||||||
@@ -156,8 +156,8 @@ extern BOOL WIN_IsEqualIID(REFIID a, REFIID b);
|
|||||||
extern void WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect);
|
extern void WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect);
|
||||||
extern void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect);
|
extern void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect);
|
||||||
|
|
||||||
// Returns true if the rect is empty
|
// Returns false if a window client rect is not valid
|
||||||
extern BOOL WIN_IsRectEmpty(const RECT *rect);
|
bool WIN_WindowRectValid(const RECT *rect);
|
||||||
|
|
||||||
extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat);
|
extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat);
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 3,2,6,0
|
FILEVERSION 3,2,14,0
|
||||||
PRODUCTVERSION 3,2,6,0
|
PRODUCTVERSION 3,2,14,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, 6, 0\0"
|
VALUE "FileVersion", "3, 2, 14, 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, 6, 0\0"
|
VALUE "ProductVersion", "3, 2, 14, 0\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|||||||
@@ -85,7 +85,9 @@
|
|||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <swis.h>
|
#include <swis.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SDL_PLATFORM_3DS
|
||||||
|
#include <3ds.h>
|
||||||
|
#endif
|
||||||
#ifdef SDL_PLATFORM_PS2
|
#ifdef SDL_PLATFORM_PS2
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -113,7 +115,11 @@
|
|||||||
#define CPU_CFG2_LSX (1 << 6)
|
#define CPU_CFG2_LSX (1 << 6)
|
||||||
#define CPU_CFG2_LASX (1 << 7)
|
#define CPU_CFG2_LASX (1 << 7)
|
||||||
|
|
||||||
#if defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) && !defined(SDL_PLATFORM_MACOS) && !defined(SDL_PLATFORM_OPENBSD) && !defined(SDL_PLATFORM_FREEBSD)
|
#if !defined(SDL_CPUINFO_DISABLED) && \
|
||||||
|
!((defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__))) || (defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__))) && \
|
||||||
|
!(defined(SDL_PLATFORM_FREEBSD) && defined(__powerpc__)) && \
|
||||||
|
!(defined(SDL_PLATFORM_LINUX) && defined(__powerpc__) && defined(HAVE_GETAUXVAL)) && \
|
||||||
|
defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP)
|
||||||
/* This is the brute force way of detecting instruction sets...
|
/* This is the brute force way of detecting instruction sets...
|
||||||
the idea is borrowed from the libmpeg2 library - thanks!
|
the idea is borrowed from the libmpeg2 library - thanks!
|
||||||
*/
|
*/
|
||||||
@@ -342,6 +348,8 @@ static int CPU_haveAltiVec(void)
|
|||||||
elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures));
|
elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures));
|
||||||
altivec = cpufeatures & PPC_FEATURE_HAS_ALTIVEC;
|
altivec = cpufeatures & PPC_FEATURE_HAS_ALTIVEC;
|
||||||
return altivec;
|
return altivec;
|
||||||
|
#elif defined(SDL_PLATFORM_LINUX) && defined(__powerpc__) && defined(HAVE_GETAUXVAL)
|
||||||
|
altivec = getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC;
|
||||||
#elif defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP)
|
#elif defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP)
|
||||||
void (*handler)(int sig);
|
void (*handler)(int sig);
|
||||||
handler = signal(SIGILL, illegal_instruction);
|
handler = signal(SIGILL, illegal_instruction);
|
||||||
@@ -642,6 +650,15 @@ int SDL_GetNumLogicalCPUCores(void)
|
|||||||
GetSystemInfo(&info);
|
GetSystemInfo(&info);
|
||||||
SDL_NumLogicalCPUCores = info.dwNumberOfProcessors;
|
SDL_NumLogicalCPUCores = info.dwNumberOfProcessors;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef SDL_PLATFORM_3DS
|
||||||
|
if (SDL_NumLogicalCPUCores <= 0) {
|
||||||
|
bool isNew3DS = false;
|
||||||
|
APT_CheckNew3DS(&isNew3DS);
|
||||||
|
// 1 core is always dedicated to the OS
|
||||||
|
// Meaning that the New3DS has 3 available core, and the Old3DS only one.
|
||||||
|
SDL_NumLogicalCPUCores = isNew3DS ? 4 : 2;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
// There has to be at least 1, right? :)
|
// There has to be at least 1, right? :)
|
||||||
if (SDL_NumLogicalCPUCores <= 0) {
|
if (SDL_NumLogicalCPUCores <= 0) {
|
||||||
@@ -1156,6 +1173,12 @@ int SDL_GetSystemRAM(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SDL_PLATFORM_3DS
|
||||||
|
if (SDL_SystemRAM <= 0) {
|
||||||
|
// The New3DS has 255MiB, the Old3DS 127MiB
|
||||||
|
SDL_SystemRAM = (int)(osGetMemRegionSize(MEMREGION_ALL) / (1024 * 1024));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef SDL_PLATFORM_VITA
|
#ifdef SDL_PLATFORM_VITA
|
||||||
if (SDL_SystemRAM <= 0) {
|
if (SDL_SystemRAM <= 0) {
|
||||||
/* Vita has 512MiB on SoC, that's split into 256MiB(+109MiB in extended memory mode) for app
|
/* Vita has 512MiB on SoC, that's split into 256MiB(+109MiB in extended memory mode) for app
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
+13
-12
@@ -110,7 +110,7 @@ typedef struct
|
|||||||
} SDL_DisabledEventBlock;
|
} SDL_DisabledEventBlock;
|
||||||
|
|
||||||
static SDL_DisabledEventBlock *SDL_disabled_events[256];
|
static SDL_DisabledEventBlock *SDL_disabled_events[256];
|
||||||
static Uint32 SDL_userevents = SDL_EVENT_USER;
|
static SDL_AtomicInt SDL_userevents;
|
||||||
|
|
||||||
typedef struct SDL_TemporaryMemory
|
typedef struct SDL_TemporaryMemory
|
||||||
{
|
{
|
||||||
@@ -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;
|
||||||
@@ -1893,9 +1892,11 @@ Uint32 SDL_RegisterEvents(int numevents)
|
|||||||
{
|
{
|
||||||
Uint32 event_base = 0;
|
Uint32 event_base = 0;
|
||||||
|
|
||||||
if ((numevents > 0) && (SDL_userevents + numevents <= SDL_EVENT_LAST)) {
|
if (numevents > 0) {
|
||||||
event_base = SDL_userevents;
|
int value = SDL_AddAtomicInt(&SDL_userevents, numevents);
|
||||||
SDL_userevents += numevents;
|
if (value >= 0 && value <= (SDL_EVENT_LAST - SDL_EVENT_USER)) {
|
||||||
|
event_base = (Uint32)(SDL_EVENT_USER + value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return event_base;
|
return event_base;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -747,7 +747,7 @@ void SDL_SendKeyboardText(const char *text)
|
|||||||
{
|
{
|
||||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||||
|
|
||||||
if (!SDL_TextInputActive(keyboard->focus)) {
|
if (!keyboard->focus || !SDL_TextInputActive(keyboard->focus)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,7 +778,7 @@ void SDL_SendEditingText(const char *text, int start, int length)
|
|||||||
{
|
{
|
||||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||||
|
|
||||||
if (!SDL_TextInputActive(keyboard->focus)) {
|
if (!keyboard->focus || !SDL_TextInputActive(keyboard->focus)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -838,7 +838,7 @@ void SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int se
|
|||||||
{
|
{
|
||||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||||
|
|
||||||
if (!SDL_TextInputActive(keyboard->focus)) {
|
if (!keyboard->focus || !SDL_TextInputActive(keyboard->focus)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
-2
@@ -234,6 +234,17 @@ static void SDLCALL SDL_MouseRelativeCursorVisibleChanged(void *userdata, const
|
|||||||
SDL_SetCursor(NULL); // Update cursor visibility
|
SDL_SetCursor(NULL); // Update cursor visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SDLCALL SDL_MouseIntegerModeChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||||
|
{
|
||||||
|
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||||
|
|
||||||
|
if (hint && *hint) {
|
||||||
|
mouse->integer_mode_flags = (Uint8)SDL_atoi(hint);
|
||||||
|
} else {
|
||||||
|
mouse->integer_mode_flags = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
bool SDL_PreInitMouse(void)
|
bool SDL_PreInitMouse(void)
|
||||||
{
|
{
|
||||||
@@ -288,6 +299,9 @@ bool SDL_PreInitMouse(void)
|
|||||||
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
|
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
|
||||||
SDL_MouseRelativeCursorVisibleChanged, mouse);
|
SDL_MouseRelativeCursorVisibleChanged, mouse);
|
||||||
|
|
||||||
|
SDL_AddHintCallback("SDL_MOUSE_INTEGER_MODE",
|
||||||
|
SDL_MouseIntegerModeChanged, mouse);
|
||||||
|
|
||||||
mouse->was_touch_mouse_events = false; // no touch to mouse movement event pending
|
mouse->was_touch_mouse_events = false; // no touch to mouse movement event pending
|
||||||
|
|
||||||
mouse->cursor_shown = true;
|
mouse->cursor_shown = true;
|
||||||
@@ -720,12 +734,22 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL
|
|||||||
y *= mouse->normal_speed_scale;
|
y *= mouse->normal_speed_scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mouse->integer_mode_flags & 1) {
|
||||||
|
// Accumulate the fractional relative motion and only process the integer portion
|
||||||
|
mouse->integer_mode_residual_motion_x = SDL_modff(mouse->integer_mode_residual_motion_x + x, &x);
|
||||||
|
mouse->integer_mode_residual_motion_y = SDL_modff(mouse->integer_mode_residual_motion_y + y, &y);
|
||||||
|
}
|
||||||
xrel = x;
|
xrel = x;
|
||||||
yrel = y;
|
yrel = y;
|
||||||
x = (mouse->last_x + xrel);
|
x = (mouse->last_x + xrel);
|
||||||
y = (mouse->last_y + yrel);
|
y = (mouse->last_y + yrel);
|
||||||
ConstrainMousePosition(mouse, window, &x, &y);
|
ConstrainMousePosition(mouse, window, &x, &y);
|
||||||
} else {
|
} else {
|
||||||
|
if (mouse->integer_mode_flags & 1) {
|
||||||
|
// Discard the fractional component from absolute coordinates
|
||||||
|
x = SDL_truncf(x);
|
||||||
|
y = SDL_truncf(y);
|
||||||
|
}
|
||||||
ConstrainMousePosition(mouse, window, &x, &y);
|
ConstrainMousePosition(mouse, window, &x, &y);
|
||||||
if (mouse->has_position) {
|
if (mouse->has_position) {
|
||||||
xrel = x - mouse->last_x;
|
xrel = x - mouse->last_x;
|
||||||
@@ -1004,6 +1028,8 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI
|
|||||||
|
|
||||||
// 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;
|
||||||
@@ -1014,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1149,9 @@ void SDL_QuitMouse(void)
|
|||||||
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
|
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
|
||||||
SDL_MouseRelativeCursorVisibleChanged, mouse);
|
SDL_MouseRelativeCursorVisibleChanged, mouse);
|
||||||
|
|
||||||
|
SDL_RemoveHintCallback("SDL_MOUSE_INTEGER_MODE",
|
||||||
|
SDL_MouseIntegerModeChanged, mouse);
|
||||||
|
|
||||||
for (int i = SDL_mouse_count; i--; ) {
|
for (int i = SDL_mouse_count; i--; ) {
|
||||||
SDL_RemoveMouse(SDL_mice[i].instance_id, false);
|
SDL_RemoveMouse(SDL_mice[i].instance_id, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,11 @@ typedef struct
|
|||||||
void (*ApplySystemScale)(void *internal, Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float *x, float *y);
|
void (*ApplySystemScale)(void *internal, Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float *x, float *y);
|
||||||
void *system_scale_data;
|
void *system_scale_data;
|
||||||
|
|
||||||
|
// integer mode data
|
||||||
|
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_y;
|
||||||
|
|
||||||
// Data common to all mice
|
// Data common to all mice
|
||||||
SDL_Window *focus;
|
SDL_Window *focus;
|
||||||
float x;
|
float x;
|
||||||
@@ -98,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+72
-4
@@ -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,11 @@ void SDL_BindGPUVertexSamplers(
|
|||||||
|
|
||||||
if (RENDERPASS_DEVICE->debug_mode) {
|
if (RENDERPASS_DEVICE->debug_mode) {
|
||||||
CHECK_RENDERPASS
|
CHECK_RENDERPASS
|
||||||
|
|
||||||
|
if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation)
|
||||||
|
{
|
||||||
|
CHECK_SAMPLER_TEXTURES
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDERPASS_DEVICE->BindVertexSamplers(
|
RENDERPASS_DEVICE->BindVertexSamplers(
|
||||||
@@ -1722,6 +1766,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 +1819,11 @@ void SDL_BindGPUFragmentSamplers(
|
|||||||
|
|
||||||
if (RENDERPASS_DEVICE->debug_mode) {
|
if (RENDERPASS_DEVICE->debug_mode) {
|
||||||
CHECK_RENDERPASS
|
CHECK_RENDERPASS
|
||||||
|
|
||||||
|
if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation)
|
||||||
|
{
|
||||||
|
CHECK_SAMPLER_TEXTURES
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDERPASS_DEVICE->BindFragmentSamplers(
|
RENDERPASS_DEVICE->BindFragmentSamplers(
|
||||||
@@ -1800,6 +1850,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 +2011,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2528,11 +2585,19 @@ void SDL_GenerateMipmapsForGPUTexture(
|
|||||||
SDL_assert_release(!"GenerateMipmaps texture must be created with SAMPLER and COLOR_TARGET usage flags!");
|
SDL_assert_release(!"GenerateMipmaps texture must be created with SAMPLER and COLOR_TARGET usage flags!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
||||||
|
commandBufferHeader->ignore_render_pass_texture_validation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_BUFFER_DEVICE->GenerateMipmaps(
|
COMMAND_BUFFER_DEVICE->GenerateMipmaps(
|
||||||
command_buffer,
|
command_buffer,
|
||||||
texture);
|
texture);
|
||||||
|
|
||||||
|
if (COMMAND_BUFFER_DEVICE->debug_mode) {
|
||||||
|
CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
|
||||||
|
commandBufferHeader->ignore_render_pass_texture_validation = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_BlitGPUTexture(
|
void SDL_BlitGPUTexture(
|
||||||
@@ -2646,8 +2711,11 @@ bool SDL_ClaimWindowForGPUDevice(
|
|||||||
{
|
{
|
||||||
CHECK_DEVICE_MAGIC(device, false);
|
CHECK_DEVICE_MAGIC(device, false);
|
||||||
if (window == NULL) {
|
if (window == NULL) {
|
||||||
SDL_InvalidParamError("window");
|
return SDL_InvalidParamError("window");
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
if ((window->flags & SDL_WINDOW_TRANSPARENT) != 0) {
|
||||||
|
return SDL_SetError("The GPU API doesn't support transparent windows");
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->ClaimWindow(
|
return device->ClaimWindow(
|
||||||
|
|||||||
+27
-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,16 +47,27 @@ 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;
|
||||||
Pass copy_pass;
|
Pass copy_pass;
|
||||||
bool swapchain_texture_acquired;
|
bool swapchain_texture_acquired;
|
||||||
bool submitted;
|
bool submitted;
|
||||||
|
// used to avoid tripping assert on GenerateMipmaps
|
||||||
|
bool ignore_render_pass_texture_validation;
|
||||||
} CommandBufferCommonHeader;
|
} CommandBufferCommonHeader;
|
||||||
|
|
||||||
typedef struct TextureCommonHeader
|
typedef struct TextureCommonHeader
|
||||||
@@ -385,21 +411,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
|
||||||
@@ -854,7 +858,7 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
|
|||||||
code,
|
code,
|
||||||
codeSize,
|
codeSize,
|
||||||
dispatch_get_global_queue(0, 0),
|
dispatch_get_global_queue(0, 0),
|
||||||
^{ /* do nothing */ });
|
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
|
||||||
library = [renderer->device newLibraryWithData:data error:&error];
|
library = [renderer->device newLibraryWithData:data error:&error];
|
||||||
} else {
|
} else {
|
||||||
SDL_assert(!"SDL_gpu.c should have already validated this!");
|
SDL_assert(!"SDL_gpu.c should have already validated this!");
|
||||||
@@ -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;
|
||||||
|
|||||||
+184
-127
@@ -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;
|
||||||
@@ -732,7 +732,7 @@ typedef struct WindowData
|
|||||||
|
|
||||||
// Synchronization primitives
|
// Synchronization primitives
|
||||||
VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
|
VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
|
||||||
VkSemaphore renderFinishedSemaphore[MAX_FRAMES_IN_FLIGHT];
|
VkSemaphore *renderFinishedSemaphore;
|
||||||
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
||||||
|
|
||||||
Uint32 frameCounter;
|
Uint32 frameCounter;
|
||||||
@@ -1135,6 +1135,7 @@ struct VulkanRenderer
|
|||||||
|
|
||||||
VulkanMemoryAllocator *memoryAllocator;
|
VulkanMemoryAllocator *memoryAllocator;
|
||||||
VkPhysicalDeviceMemoryProperties memoryProperties;
|
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||||
|
bool checkEmptyAllocations;
|
||||||
|
|
||||||
WindowData **claimedWindows;
|
WindowData **claimedWindows;
|
||||||
Uint32 claimedWindowCount;
|
Uint32 claimedWindowCount;
|
||||||
@@ -1203,7 +1204,11 @@ struct VulkanRenderer
|
|||||||
SDL_Mutex *submitLock;
|
SDL_Mutex *submitLock;
|
||||||
SDL_Mutex *acquireCommandBufferLock;
|
SDL_Mutex *acquireCommandBufferLock;
|
||||||
SDL_Mutex *acquireUniformBufferLock;
|
SDL_Mutex *acquireUniformBufferLock;
|
||||||
|
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;
|
||||||
@@ -1221,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);
|
||||||
@@ -1253,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!";
|
||||||
}
|
}
|
||||||
@@ -1577,6 +1583,10 @@ static void VULKAN_INTERNAL_RemoveMemoryUsedRegion(
|
|||||||
usedRegion->offset,
|
usedRegion->offset,
|
||||||
usedRegion->size);
|
usedRegion->size);
|
||||||
|
|
||||||
|
if (usedRegion->allocation->usedRegionCount == 0) {
|
||||||
|
renderer->checkEmptyAllocations = true;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_free(usedRegion);
|
SDL_free(usedRegion);
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
@@ -3169,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3207,7 +3217,6 @@ static void VULKAN_INTERNAL_DestroySwapchain(
|
|||||||
SDL_free(windowData->textureContainers[i].activeTexture->subresources);
|
SDL_free(windowData->textureContainers[i].activeTexture->subresources);
|
||||||
SDL_free(windowData->textureContainers[i].activeTexture);
|
SDL_free(windowData->textureContainers[i].activeTexture);
|
||||||
}
|
}
|
||||||
windowData->imageCount = 0;
|
|
||||||
|
|
||||||
SDL_free(windowData->textureContainers);
|
SDL_free(windowData->textureContainers);
|
||||||
windowData->textureContainers = NULL;
|
windowData->textureContainers = NULL;
|
||||||
@@ -3236,7 +3245,8 @@ static void VULKAN_INTERNAL_DestroySwapchain(
|
|||||||
NULL);
|
NULL);
|
||||||
windowData->imageAvailableSemaphore[i] = VK_NULL_HANDLE;
|
windowData->imageAvailableSemaphore[i] = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < windowData->imageCount; i += 1) {
|
||||||
if (windowData->renderFinishedSemaphore[i]) {
|
if (windowData->renderFinishedSemaphore[i]) {
|
||||||
renderer->vkDestroySemaphore(
|
renderer->vkDestroySemaphore(
|
||||||
renderer->logicalDevice,
|
renderer->logicalDevice,
|
||||||
@@ -3245,6 +3255,10 @@ static void VULKAN_INTERNAL_DestroySwapchain(
|
|||||||
windowData->renderFinishedSemaphore[i] = VK_NULL_HANDLE;
|
windowData->renderFinishedSemaphore[i] = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SDL_free(windowData->renderFinishedSemaphore);
|
||||||
|
windowData->renderFinishedSemaphore = NULL;
|
||||||
|
|
||||||
|
windowData->imageCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(
|
static void VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(
|
||||||
@@ -3744,10 +3758,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3830,7 +3847,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;
|
||||||
@@ -3852,6 +3872,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3872,10 +3893,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3958,6 +3983,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3969,6 +3995,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3987,10 +4014,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4059,6 +4089,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4070,6 +4101,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4634,7 +4666,11 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
swapchainCreateInfo.queueFamilyIndexCount = 0;
|
swapchainCreateInfo.queueFamilyIndexCount = 0;
|
||||||
swapchainCreateInfo.pQueueFamilyIndices = NULL;
|
swapchainCreateInfo.pQueueFamilyIndices = NULL;
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID
|
||||||
swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||||
|
#else
|
||||||
|
swapchainCreateInfo.preTransform = swapchainSupportDetails.capabilities.currentTransform;
|
||||||
|
#endif
|
||||||
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
swapchainCreateInfo.presentMode = SDLToVK_PresentMode[windowData->presentMode];
|
swapchainCreateInfo.presentMode = SDLToVK_PresentMode[windowData->presentMode];
|
||||||
swapchainCreateInfo.clipped = VK_TRUE;
|
swapchainCreateInfo.clipped = VK_TRUE;
|
||||||
@@ -4780,7 +4816,13 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
|
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->vkCreateSemaphore(
|
windowData->inFlightFences[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
windowData->renderFinishedSemaphore = SDL_malloc(
|
||||||
|
sizeof(VkSemaphore) * windowData->imageCount);
|
||||||
|
for (i = 0; i < windowData->imageCount; i += 1) {
|
||||||
|
vulkanResult = renderer->vkCreateSemaphore(
|
||||||
renderer->logicalDevice,
|
renderer->logicalDevice,
|
||||||
&semaphoreCreateInfo,
|
&semaphoreCreateInfo,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -4799,8 +4841,6 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
windowData->swapchain = VK_NULL_HANDLE;
|
windowData->swapchain = VK_NULL_HANDLE;
|
||||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
|
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
windowData->inFlightFences[i] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
windowData->needsSwapchainRecreate = false;
|
windowData->needsSwapchainRecreate = false;
|
||||||
@@ -4934,7 +4974,11 @@ static void VULKAN_DestroyDevice(
|
|||||||
SDL_DestroyMutex(renderer->submitLock);
|
SDL_DestroyMutex(renderer->submitLock);
|
||||||
SDL_DestroyMutex(renderer->acquireCommandBufferLock);
|
SDL_DestroyMutex(renderer->acquireCommandBufferLock);
|
||||||
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
|
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
|
||||||
|
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);
|
||||||
@@ -5591,6 +5635,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;
|
||||||
@@ -5818,15 +5863,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;
|
||||||
}
|
}
|
||||||
@@ -5876,6 +5923,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;
|
||||||
@@ -5893,8 +5941,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;
|
||||||
}
|
}
|
||||||
@@ -5958,6 +6013,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(
|
||||||
@@ -6671,7 +6727,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;
|
||||||
@@ -6691,10 +6746,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;
|
||||||
@@ -6740,6 +6796,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) {
|
||||||
@@ -6751,7 +6808,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;
|
||||||
@@ -6914,7 +6973,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);
|
||||||
@@ -7081,12 +7140,15 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
|
|||||||
key.depthStencilTargetDescription.stencilStoreOp = depthStencilTargetInfo->stencil_store_op;
|
key.depthStencilTargetDescription.stencilStoreOp = depthStencilTargetInfo->stencil_store_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_LockMutex(renderer->renderPassFetchLock);
|
||||||
|
|
||||||
bool result = SDL_FindInHashTable(
|
bool result = SDL_FindInHashTable(
|
||||||
renderer->renderPassHashTable,
|
renderer->renderPassHashTable,
|
||||||
(const void *)&key,
|
(const void *)&key,
|
||||||
(const void **)&renderPassWrapper);
|
(const void **)&renderPassWrapper);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
|
SDL_UnlockMutex(renderer->renderPassFetchLock);
|
||||||
return renderPassWrapper->handle;
|
return renderPassWrapper->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7098,6 +7160,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
|
|||||||
depthStencilTargetInfo);
|
depthStencilTargetInfo);
|
||||||
|
|
||||||
if (renderPassHandle == VK_NULL_HANDLE) {
|
if (renderPassHandle == VK_NULL_HANDLE) {
|
||||||
|
SDL_UnlockMutex(renderer->renderPassFetchLock);
|
||||||
return VK_NULL_HANDLE;
|
return VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7113,6 +7176,8 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
|
|||||||
(const void *)allocedKey,
|
(const void *)allocedKey,
|
||||||
(const void *)renderPassWrapper, true);
|
(const void *)renderPassWrapper, true);
|
||||||
|
|
||||||
|
SDL_UnlockMutex(renderer->renderPassFetchLock);
|
||||||
|
|
||||||
return renderPassHandle;
|
return renderPassHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7181,9 +7246,8 @@ static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
|
|||||||
(const void *)&key,
|
(const void *)&key,
|
||||||
(const void **)&vulkanFramebuffer);
|
(const void **)&vulkanFramebuffer);
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->framebufferFetchLock);
|
|
||||||
|
|
||||||
if (findResult) {
|
if (findResult) {
|
||||||
|
SDL_UnlockMutex(renderer->framebufferFetchLock);
|
||||||
return vulkanFramebuffer;
|
return vulkanFramebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7251,19 +7315,18 @@ static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
|
|||||||
FramebufferHashTableKey *allocedKey = SDL_malloc(sizeof(FramebufferHashTableKey));
|
FramebufferHashTableKey *allocedKey = SDL_malloc(sizeof(FramebufferHashTableKey));
|
||||||
SDL_memcpy(allocedKey, &key, sizeof(FramebufferHashTableKey));
|
SDL_memcpy(allocedKey, &key, sizeof(FramebufferHashTableKey));
|
||||||
|
|
||||||
SDL_LockMutex(renderer->framebufferFetchLock);
|
|
||||||
|
|
||||||
SDL_InsertIntoHashTable(
|
SDL_InsertIntoHashTable(
|
||||||
renderer->framebufferHashTable,
|
renderer->framebufferHashTable,
|
||||||
(const void *)allocedKey,
|
(const void *)allocedKey,
|
||||||
(const void *)vulkanFramebuffer, true);
|
(const void *)vulkanFramebuffer, true);
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->framebufferFetchLock);
|
|
||||||
} else {
|
} else {
|
||||||
SDL_free(vulkanFramebuffer);
|
SDL_free(vulkanFramebuffer);
|
||||||
|
SDL_UnlockMutex(renderer->framebufferFetchLock);
|
||||||
CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateFramebuffer, NULL);
|
CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateFramebuffer, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_UnlockMutex(renderer->framebufferFetchLock);
|
||||||
return vulkanFramebuffer;
|
return vulkanFramebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7928,11 +7991,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8095,7 +8158,7 @@ static void VULKAN_BeginComputePass(
|
|||||||
vulkanCommandBuffer,
|
vulkanCommandBuffer,
|
||||||
bufferContainer,
|
bufferContainer,
|
||||||
storageBufferBindings[i].cycle,
|
storageBufferBindings[i].cycle,
|
||||||
VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ);
|
VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
|
||||||
|
|
||||||
vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = buffer;
|
vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = buffer;
|
||||||
|
|
||||||
@@ -9966,7 +10029,7 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
|
|||||||
}
|
}
|
||||||
|
|
||||||
vulkanCommandBuffer->signalSemaphores[vulkanCommandBuffer->signalSemaphoreCount] =
|
vulkanCommandBuffer->signalSemaphores[vulkanCommandBuffer->signalSemaphoreCount] =
|
||||||
windowData->renderFinishedSemaphore[windowData->frameCounter];
|
windowData->renderFinishedSemaphore[swapchainImageIndex];
|
||||||
vulkanCommandBuffer->signalSemaphoreCount += 1;
|
vulkanCommandBuffer->signalSemaphoreCount += 1;
|
||||||
|
|
||||||
*swapchainTexture = (SDL_GPUTexture *)swapchainTextureContainer;
|
*swapchainTexture = (SDL_GPUTexture *)swapchainTextureContainer;
|
||||||
@@ -10429,9 +10492,10 @@ static bool VULKAN_Submit(
|
|||||||
VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT];
|
VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT];
|
||||||
Uint32 swapchainImageIndex;
|
Uint32 swapchainImageIndex;
|
||||||
VulkanTextureSubresource *swapchainTextureSubresource;
|
VulkanTextureSubresource *swapchainTextureSubresource;
|
||||||
Uint8 commandBufferCleaned = 0;
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -10454,6 +10518,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;
|
||||||
@@ -10491,17 +10564,13 @@ 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;
|
||||||
presentInfo.pNext = NULL;
|
presentInfo.pNext = NULL;
|
||||||
presentInfo.pWaitSemaphores =
|
presentInfo.pWaitSemaphores =
|
||||||
&presentData->windowData->renderFinishedSemaphore[presentData->windowData->frameCounter];
|
&presentData->windowData->renderFinishedSemaphore[presentData->swapchainImageIndex];
|
||||||
presentInfo.waitSemaphoreCount = 1;
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
presentInfo.pSwapchains = &presentData->windowData->swapchain;
|
presentInfo.pSwapchains = &presentData->windowData->swapchain;
|
||||||
presentInfo.swapchainCount = 1;
|
presentInfo.swapchainCount = 1;
|
||||||
@@ -10533,60 +10602,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);
|
|
||||||
|
|
||||||
commandBufferCleaned = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandBufferCleaned) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
if (renderer->checkEmptyAllocations) {
|
||||||
}
|
SDL_LockMutex(renderer->allocatorLock);
|
||||||
|
|
||||||
// Check pending destroys
|
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
|
||||||
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
|
allocator = &renderer->memoryAllocator->subAllocators[i];
|
||||||
|
|
||||||
// Defrag!
|
for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
|
||||||
if (
|
if (allocator->allocations[j]->usedRegionCount == 0) {
|
||||||
presenting &&
|
VULKAN_INTERNAL_DeallocateMemory(
|
||||||
renderer->allocationsToDefragCount > 0 &&
|
renderer,
|
||||||
!renderer->defragInProgress) {
|
allocator,
|
||||||
result = VULKAN_INTERNAL_DefragmentMemory(renderer);
|
j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->checkEmptyAllocations = false;
|
||||||
|
|
||||||
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
@@ -10613,43 +10672,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,
|
||||||
@@ -10659,6 +10703,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10677,6 +10722,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;
|
||||||
@@ -10716,20 +10762,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,
|
||||||
@@ -10737,12 +10785,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;
|
||||||
@@ -10794,8 +10844,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
|
||||||
@@ -11560,7 +11609,7 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
|
|||||||
{
|
{
|
||||||
// Set up dummy VulkanRenderer
|
// Set up dummy VulkanRenderer
|
||||||
VulkanRenderer *renderer;
|
VulkanRenderer *renderer;
|
||||||
Uint8 result;
|
bool result = false;
|
||||||
|
|
||||||
if (_this->Vulkan_CreateSurface == NULL) {
|
if (_this->Vulkan_CreateSurface == NULL) {
|
||||||
return false;
|
return false;
|
||||||
@@ -11570,16 +11619,16 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
|
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
|
||||||
SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
|
if (renderer) {
|
||||||
|
result = VULKAN_INTERNAL_PrepareVulkan(renderer);
|
||||||
result = VULKAN_INTERNAL_PrepareVulkan(renderer);
|
if (result) {
|
||||||
|
renderer->vkDestroyInstance(renderer->instance, NULL);
|
||||||
if (result) {
|
}
|
||||||
renderer->vkDestroyInstance(renderer->instance, NULL);
|
SDL_free(renderer);
|
||||||
}
|
}
|
||||||
SDL_free(renderer);
|
|
||||||
SDL_Vulkan_UnloadLibrary();
|
SDL_Vulkan_UnloadLibrary();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11595,8 +11644,12 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
|
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
|
||||||
SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
|
if (!renderer) {
|
||||||
|
SDL_Vulkan_UnloadLibrary();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
renderer->debugMode = debugMode;
|
renderer->debugMode = debugMode;
|
||||||
renderer->preferLowPower = preferLowPower;
|
renderer->preferLowPower = preferLowPower;
|
||||||
renderer->allowedFramesInFlight = 2;
|
renderer->allowedFramesInFlight = 2;
|
||||||
@@ -11657,7 +11710,11 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
renderer->submitLock = SDL_CreateMutex();
|
renderer->submitLock = SDL_CreateMutex();
|
||||||
renderer->acquireCommandBufferLock = SDL_CreateMutex();
|
renderer->acquireCommandBufferLock = SDL_CreateMutex();
|
||||||
renderer->acquireUniformBufferLock = SDL_CreateMutex();
|
renderer->acquireUniformBufferLock = 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();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -11718,7 +11775,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.
|
||||||
true, // thread-safe
|
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,
|
||||||
@@ -11734,7 +11791,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,
|
||||||
@@ -11742,7 +11799,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,
|
||||||
@@ -11750,7 +11807,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,
|
||||||
|
|||||||
@@ -807,6 +807,8 @@ typedef struct LIBUSB_hid_device_ LIBUSB_hid_device;
|
|||||||
#define hid_send_feature_report LIBUSB_hid_send_feature_report
|
#define hid_send_feature_report LIBUSB_hid_send_feature_report
|
||||||
#define hid_set_nonblocking LIBUSB_hid_set_nonblocking
|
#define hid_set_nonblocking LIBUSB_hid_set_nonblocking
|
||||||
#define hid_write LIBUSB_hid_write
|
#define hid_write LIBUSB_hid_write
|
||||||
|
#define hid_version LIBUSB_hid_version
|
||||||
|
#define hid_version_str LIBUSB_hid_version_str
|
||||||
#define input_report LIBUSB_input_report
|
#define input_report LIBUSB_input_report
|
||||||
#define make_path LIBUSB_make_path
|
#define make_path LIBUSB_make_path
|
||||||
#define new_hid_device LIBUSB_new_hid_device
|
#define new_hid_device LIBUSB_new_hid_device
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|
||||||
|
|||||||
@@ -309,12 +309,13 @@ bool SDL_LoadFileAsync(const char *file, SDL_AsyncIOQueue *queue, void *userdata
|
|||||||
if (asyncio) {
|
if (asyncio) {
|
||||||
asyncio->oneshot = true;
|
asyncio->oneshot = true;
|
||||||
|
|
||||||
void *ptr = NULL;
|
Uint8 *ptr = NULL;
|
||||||
const Sint64 flen = SDL_GetAsyncIOSize(asyncio);
|
const Sint64 flen = SDL_GetAsyncIOSize(asyncio);
|
||||||
if (flen >= 0) {
|
if (flen >= 0) {
|
||||||
// !!! FIXME: check if flen > address space, since it'll truncate and we'll just end up with an incomplete buffer or a crash.
|
// !!! FIXME: check if flen > address space, since it'll truncate and we'll just end up with an incomplete buffer or a crash.
|
||||||
ptr = SDL_malloc((size_t) (flen + 1)); // over-allocate by one so we can add a null-terminator.
|
ptr = (Uint8 *) SDL_malloc((size_t) (flen + 1)); // over-allocate by one so we can add a null-terminator.
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
|
ptr[flen] = '\0';
|
||||||
retval = SDL_ReadAsyncIO(asyncio, ptr, 0, (Uint64) flen, queue, userdata);
|
retval = SDL_ReadAsyncIO(asyncio, ptr, 0, (Uint64) flen, queue, userdata);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
SDL_free(ptr);
|
SDL_free(ptr);
|
||||||
|
|||||||
+21
-16
@@ -405,15 +405,17 @@ static bool SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
|
|||||||
{
|
{
|
||||||
SDL_AssertJoysticksLocked();
|
SDL_AssertJoysticksLocked();
|
||||||
|
|
||||||
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
|
if (SDL_EventEnabled(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE)) {
|
||||||
if (gamepad->joystick->instance_id == event->jdevice.which) {
|
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
|
||||||
SDL_Event deviceevent;
|
if (gamepad->joystick->instance_id == event->jdevice.which) {
|
||||||
|
SDL_Event deviceevent;
|
||||||
|
|
||||||
deviceevent.type = SDL_EVENT_GAMEPAD_UPDATE_COMPLETE;
|
deviceevent.type = SDL_EVENT_GAMEPAD_UPDATE_COMPLETE;
|
||||||
deviceevent.common.timestamp = event->jdevice.timestamp;
|
deviceevent.common.timestamp = event->jdevice.timestamp;
|
||||||
deviceevent.gdevice.which = event->jdevice.which;
|
deviceevent.gdevice.which = event->jdevice.which;
|
||||||
SDL_PushEvent(&deviceevent);
|
SDL_PushEvent(&deviceevent);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -729,7 +731,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
|
|||||||
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,", 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,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string));
|
||||||
break;
|
break;
|
||||||
case k_eSwitchDeviceInfoControllerType_SNES:
|
case k_eSwitchDeviceInfoControllerType_SNES:
|
||||||
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,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,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
|
||||||
break;
|
break;
|
||||||
case k_eSwitchDeviceInfoControllerType_N64:
|
case k_eSwitchDeviceInfoControllerType_N64:
|
||||||
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,righttrigger:a5,start:b6,x:b2,y:b3,misc1:b11,", 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,righttrigger:a5,start:b6,x:b2,y:b3,misc1:b11,", sizeof(mapping_string));
|
||||||
@@ -773,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) ||
|
||||||
@@ -820,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
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ static const char *s_GamepadMappings[] = {
|
|||||||
"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,",
|
"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,",
|
||||||
"03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,",
|
"03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,",
|
||||||
"030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,",
|
"030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,",
|
||||||
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,start:b11,x:b3,y:b4,",
|
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:-a5,start:b11,x:b3,y:b4,",
|
||||||
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,",
|
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,",
|
||||||
"030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
|
"030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
|
||||||
"03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
"03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||||
@@ -421,7 +421,7 @@ static const char *s_GamepadMappings[] = {
|
|||||||
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
|
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
|
||||||
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,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,",
|
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,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,",
|
||||||
"050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,start:b11,x:b3,y:b4,",
|
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:a5,start:b11,x:b3,y:b4,",
|
||||||
"030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
|
"030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
|
||||||
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||||
"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||||
@@ -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,",
|
||||||
@@ -641,6 +642,12 @@ static const char *s_GamepadMappings[] = {
|
|||||||
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
|
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
|
||||||
"03000000451300000830000010010000,NYKO CORE,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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
"03000000451300000830000010010000,NYKO CORE,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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||||
"03000000790000004318000010010000,Nintendo GameCube Controller,a:b1,b:b0,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:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"03000000790000004318000010010000,Nintendo GameCube Controller,a:b1,b:b0,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:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
|
"030000007e0500001920000011810000,Nintendo N64 Controller,crc:d670,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b3,start:b11,x:b4,y:b10,",
|
||||||
|
"050000007e0500001920000001800000,Nintendo N64 Controller,crc:5e1c,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b3,start:b11,x:b4,y:b10,",
|
||||||
|
"030000007e0500001e20000011810000,Nintendo SEGA Genesis Controller,crc:bb22,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,",
|
||||||
|
"050000007e0500001720000001800000,Nintendo SEGA Genesis Controller,crc:c1bf,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,",
|
||||||
|
"030000007e0500001720000011810000,Nintendo SNES Controller,crc:f648,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
|
"050000007e0500001720000001800000,Nintendo SNES Controller,crc:dbc0,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
"050000007e0500000620000001800000,Nintendo Switch Joy-Con (L),a:b16,b:b15,guide:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"050000007e0500000620000001800000,Nintendo Switch Joy-Con (L),a:b16,b:b15,guide:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
"060000007e0500000620000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"060000007e0500000620000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
"060000007e0500000820000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"060000007e0500000820000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
@@ -861,7 +868,9 @@ static const char *s_GamepadMappings[] = {
|
|||||||
"05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
|
"05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
|
||||||
"05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,",
|
"05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,",
|
||||||
"05000000ac05000004000000a8986d04,8BitDo Micro gamepad,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"05000000ac05000004000000a8986d04,8BitDo Micro gamepad,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
|
"05000000ac05000004000000fd216d04,8BitDo Pro 2,crc:ac95,a:b3,b:b2,back:b6,dpdown:b9,dpleft:b10,dpright:b11,dpup:b12,guide:b4,leftshoulder:b13,leftstick:b14,lefttrigger:+a2,leftx:a0,lefty:a1~,paddle1:b1,paddle2:b0,rightshoulder:b16,rightstick:b17,righttrigger:+a5,rightx:a3,righty:a4~,start:b5,x:b8,y:b7,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
"05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,crc:3e00,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,crc:3e00,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
|
"05000000ac05000004000000209f6d04,8Bitdo SN30 Pro,crc:40d6,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
"050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
|
"050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
|
||||||
"050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
|
"050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
|
||||||
"050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
"050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||||
@@ -898,7 +907,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
|
||||||
};
|
};
|
||||||
+101
-1
@@ -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)
|
||||||
@@ -427,6 +447,13 @@ static SDL_vidpid_list zero_centered_devices = {
|
|||||||
return result; \
|
return result; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHECK_JOYSTICK_VIRTUAL(joystick, result) \
|
||||||
|
if (!joystick->is_virtual) { \
|
||||||
|
SDL_SetError("joystick isn't virtual"); \
|
||||||
|
SDL_UnlockJoysticks(); \
|
||||||
|
return result; \
|
||||||
|
}
|
||||||
|
|
||||||
bool SDL_JoysticksInitialized(void)
|
bool SDL_JoysticksInitialized(void)
|
||||||
{
|
{
|
||||||
return SDL_joysticks_initialized;
|
return SDL_joysticks_initialized;
|
||||||
@@ -1043,6 +1070,27 @@ static void CleanupSensorFusion(SDL_Joystick *joystick)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ShouldSwapFaceButtons(const SDL_SteamVirtualGamepadInfo *info)
|
||||||
|
{
|
||||||
|
// When "Use Nintendo Button Layout" is enabled under Steam (the default)
|
||||||
|
// it will send button 0 for the A (east) button and button 1 for the
|
||||||
|
// B (south) button. This is done so that games that interpret the
|
||||||
|
// buttons as Xbox input will get button 0 for "A" as they expect.
|
||||||
|
//
|
||||||
|
// However, SDL reports positional buttons, so we need to swap
|
||||||
|
// the buttons so they show up in the correct position. This provides
|
||||||
|
// consistent behavior regardless of whether we're running under Steam,
|
||||||
|
// under the default settings.
|
||||||
|
if (info &&
|
||||||
|
(info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO ||
|
||||||
|
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT ||
|
||||||
|
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT ||
|
||||||
|
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open a joystick for use - the index passed as an argument refers to
|
* Open a joystick for use - the index passed as an argument refers to
|
||||||
* the N'th joystick on the system. This index is the value which will
|
* the N'th joystick on the system. This index is the value which will
|
||||||
@@ -1094,6 +1142,11 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
|
|||||||
joystick->attached = true;
|
joystick->attached = true;
|
||||||
joystick->led_expiration = SDL_GetTicks();
|
joystick->led_expiration = SDL_GetTicks();
|
||||||
joystick->battery_percent = -1;
|
joystick->battery_percent = -1;
|
||||||
|
#ifdef SDL_JOYSTICK_VIRTUAL
|
||||||
|
joystick->is_virtual = (driver == &SDL_VIRTUAL_JoystickDriver);
|
||||||
|
#else
|
||||||
|
joystick->is_virtual = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!driver->Open(joystick, device_index)) {
|
if (!driver->Open(joystick, device_index)) {
|
||||||
SDL_SetObjectValid(joystick, SDL_OBJECT_TYPE_JOYSTICK, false);
|
SDL_SetObjectValid(joystick, SDL_OBJECT_TYPE_JOYSTICK, false);
|
||||||
@@ -1148,6 +1201,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
|
|||||||
info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id);
|
info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id);
|
||||||
if (info) {
|
if (info) {
|
||||||
joystick->steam_handle = info->handle;
|
joystick->steam_handle = info->handle;
|
||||||
|
joystick->swap_face_buttons = ShouldSwapFaceButtons(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use system gyro and accelerometer if the gamepad doesn't have built-in sensors
|
// Use system gyro and accelerometer if the gamepad doesn't have built-in sensors
|
||||||
@@ -1225,6 +1279,7 @@ bool SDL_SetJoystickVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value)
|
|||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
{
|
{
|
||||||
CHECK_JOYSTICK_MAGIC(joystick, false);
|
CHECK_JOYSTICK_MAGIC(joystick, false);
|
||||||
|
CHECK_JOYSTICK_VIRTUAL(joystick, false);
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_VIRTUAL
|
#ifdef SDL_JOYSTICK_VIRTUAL
|
||||||
result = SDL_SetJoystickVirtualAxisInner(joystick, axis, value);
|
result = SDL_SetJoystickVirtualAxisInner(joystick, axis, value);
|
||||||
@@ -1244,6 +1299,7 @@ bool SDL_SetJoystickVirtualBall(SDL_Joystick *joystick, int ball, Sint16 xrel, S
|
|||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
{
|
{
|
||||||
CHECK_JOYSTICK_MAGIC(joystick, false);
|
CHECK_JOYSTICK_MAGIC(joystick, false);
|
||||||
|
CHECK_JOYSTICK_VIRTUAL(joystick, false);
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_VIRTUAL
|
#ifdef SDL_JOYSTICK_VIRTUAL
|
||||||
result = SDL_SetJoystickVirtualBallInner(joystick, ball, xrel, yrel);
|
result = SDL_SetJoystickVirtualBallInner(joystick, ball, xrel, yrel);
|
||||||
@@ -1263,6 +1319,7 @@ bool SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, int button, bool down)
|
|||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
{
|
{
|
||||||
CHECK_JOYSTICK_MAGIC(joystick, false);
|
CHECK_JOYSTICK_MAGIC(joystick, false);
|
||||||
|
CHECK_JOYSTICK_VIRTUAL(joystick, false);
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_VIRTUAL
|
#ifdef SDL_JOYSTICK_VIRTUAL
|
||||||
result = SDL_SetJoystickVirtualButtonInner(joystick, button, down);
|
result = SDL_SetJoystickVirtualButtonInner(joystick, button, down);
|
||||||
@@ -1282,6 +1339,7 @@ bool SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value)
|
|||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
{
|
{
|
||||||
CHECK_JOYSTICK_MAGIC(joystick, false);
|
CHECK_JOYSTICK_MAGIC(joystick, false);
|
||||||
|
CHECK_JOYSTICK_VIRTUAL(joystick, false);
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_VIRTUAL
|
#ifdef SDL_JOYSTICK_VIRTUAL
|
||||||
result = SDL_SetJoystickVirtualHatInner(joystick, hat, value);
|
result = SDL_SetJoystickVirtualHatInner(joystick, hat, value);
|
||||||
@@ -1301,6 +1359,7 @@ bool SDL_SetJoystickVirtualTouchpad(SDL_Joystick *joystick, int touchpad, int fi
|
|||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
{
|
{
|
||||||
CHECK_JOYSTICK_MAGIC(joystick, false);
|
CHECK_JOYSTICK_MAGIC(joystick, false);
|
||||||
|
CHECK_JOYSTICK_VIRTUAL(joystick, false);
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_VIRTUAL
|
#ifdef SDL_JOYSTICK_VIRTUAL
|
||||||
result = SDL_SetJoystickVirtualTouchpadInner(joystick, touchpad, finger, down, x, y, pressure);
|
result = SDL_SetJoystickVirtualTouchpadInner(joystick, touchpad, finger, down, x, y, pressure);
|
||||||
@@ -1320,6 +1379,7 @@ bool SDL_SendJoystickVirtualSensorData(SDL_Joystick *joystick, SDL_SensorType ty
|
|||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
{
|
{
|
||||||
CHECK_JOYSTICK_MAGIC(joystick, false);
|
CHECK_JOYSTICK_MAGIC(joystick, false);
|
||||||
|
CHECK_JOYSTICK_VIRTUAL(joystick, false);
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_VIRTUAL
|
#ifdef SDL_JOYSTICK_VIRTUAL
|
||||||
result = SDL_SendJoystickVirtualSensorDataInner(joystick, type, sensor_timestamp, data, num_values);
|
result = SDL_SendJoystickVirtualSensorDataInner(joystick, type, sensor_timestamp, data, num_values);
|
||||||
@@ -1778,6 +1838,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) {
|
||||||
@@ -1788,6 +1856,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2305,6 +2374,25 @@ void SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butt
|
|||||||
event.type = SDL_EVENT_JOYSTICK_BUTTON_UP;
|
event.type = SDL_EVENT_JOYSTICK_BUTTON_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (joystick->swap_face_buttons) {
|
||||||
|
switch (button) {
|
||||||
|
case 0:
|
||||||
|
button = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
button = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
button = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
button = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we're not getting garbage or duplicate events
|
// Make sure we're not getting garbage or duplicate events
|
||||||
if (button >= joystick->nbuttons) {
|
if (button >= joystick->nbuttons) {
|
||||||
return;
|
return;
|
||||||
@@ -2353,11 +2441,13 @@ static void SendSteamHandleUpdateEvents(void)
|
|||||||
if (info) {
|
if (info) {
|
||||||
if (joystick->steam_handle != info->handle) {
|
if (joystick->steam_handle != info->handle) {
|
||||||
joystick->steam_handle = info->handle;
|
joystick->steam_handle = info->handle;
|
||||||
|
joystick->swap_face_buttons = ShouldSwapFaceButtons(info);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (joystick->steam_handle != 0) {
|
if (joystick->steam_handle != 0) {
|
||||||
joystick->steam_handle = 0;
|
joystick->steam_handle = 0;
|
||||||
|
joystick->swap_face_buttons = false;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2421,6 +2511,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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2801,7 +2900,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ struct SDL_Joystick
|
|||||||
SDL_GUID guid _guarded; // Joystick guid
|
SDL_GUID guid _guarded; // Joystick guid
|
||||||
Uint16 firmware_version _guarded; // Firmware version, if available
|
Uint16 firmware_version _guarded; // Firmware version, if available
|
||||||
Uint64 steam_handle _guarded; // Steam controller API handle
|
Uint64 steam_handle _guarded; // Steam controller API handle
|
||||||
|
bool swap_face_buttons _guarded; // Whether we should swap face buttons
|
||||||
|
bool is_virtual _guarded; // Whether this is a virtual joystick
|
||||||
|
|
||||||
int naxes _guarded; // Number of axis controls on the joystick
|
int naxes _guarded; // Number of axis controls on the joystick
|
||||||
SDL_JoystickAxisInfo *axes _guarded;
|
SDL_JoystickAxisInfo *axes _guarded;
|
||||||
@@ -111,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;
|
||||||
|
|||||||
@@ -868,10 +868,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SDL_SetObjectValid(device, SDL_OBJECT_TYPE_HIDAPI_JOYSTICK, true);
|
SDL_SetObjectValid(device, SDL_OBJECT_TYPE_HIDAPI_JOYSTICK, true);
|
||||||
device->path = SDL_strdup(info->path);
|
if (info->path) {
|
||||||
if (!device->path) {
|
device->path = SDL_strdup(info->path);
|
||||||
SDL_free(device);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
device->seen = true;
|
device->seen = true;
|
||||||
device->vendor_id = info->vendor_id;
|
device->vendor_id = info->vendor_id;
|
||||||
@@ -1135,12 +1133,13 @@ check_removed:
|
|||||||
goto check_removed;
|
goto check_removed;
|
||||||
} else {
|
} else {
|
||||||
HIDAPI_DelDevice(device);
|
HIDAPI_DelDevice(device);
|
||||||
|
device = NULL;
|
||||||
|
|
||||||
// Update the device list again in case this device comes back
|
// Update the device list again in case this device comes back
|
||||||
SDL_HIDAPI_change_count = 0;
|
SDL_HIDAPI_change_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (device->broken && device->parent) {
|
if (device && device->broken && device->parent) {
|
||||||
HIDAPI_DelDevice(device->parent);
|
HIDAPI_DelDevice(device->parent);
|
||||||
|
|
||||||
// We deleted a different device here, restart the loop
|
// We deleted a different device here, restart the loop
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -158,8 +158,11 @@ struct joystick_hwdata
|
|||||||
Uint8 wgi_correlation_count;
|
Uint8 wgi_correlation_count;
|
||||||
Uint8 wgi_uncorrelate_count;
|
Uint8 wgi_uncorrelate_count;
|
||||||
WindowsGamingInputGamepadState *wgi_slot;
|
WindowsGamingInputGamepadState *wgi_slot;
|
||||||
|
struct __x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool triggers_rumbling;
|
||||||
|
|
||||||
SDL_RAWINPUT_Device *device;
|
SDL_RAWINPUT_Device *device;
|
||||||
};
|
};
|
||||||
typedef struct joystick_hwdata RAWINPUT_DeviceContext;
|
typedef struct joystick_hwdata RAWINPUT_DeviceContext;
|
||||||
@@ -447,7 +450,6 @@ typedef struct WindowsGamingInputGamepadState
|
|||||||
bool used; // Is currently mapped to an SDL device
|
bool used; // Is currently mapped to an SDL device
|
||||||
bool connected; // Just used during update to track disconnected
|
bool connected; // Just used during update to track disconnected
|
||||||
Uint8 correlation_id;
|
Uint8 correlation_id;
|
||||||
struct __x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration;
|
|
||||||
} WindowsGamingInputGamepadState;
|
} WindowsGamingInputGamepadState;
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
@@ -909,9 +911,11 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
|
|||||||
char *product_string = NULL;
|
char *product_string = NULL;
|
||||||
WCHAR string[128];
|
WCHAR string[128];
|
||||||
|
|
||||||
|
string[0] = 0;
|
||||||
if (SDL_HidD_GetManufacturerString(hFile, string, sizeof(string))) {
|
if (SDL_HidD_GetManufacturerString(hFile, string, sizeof(string))) {
|
||||||
manufacturer_string = WIN_StringToUTF8W(string);
|
manufacturer_string = WIN_StringToUTF8W(string);
|
||||||
}
|
}
|
||||||
|
string[0] = 0;
|
||||||
if (SDL_HidD_GetProductString(hFile, string, sizeof(string))) {
|
if (SDL_HidD_GetProductString(hFile, string, sizeof(string))) {
|
||||||
product_string = WIN_StringToUTF8W(string);
|
product_string = WIN_StringToUTF8W(string);
|
||||||
}
|
}
|
||||||
@@ -1459,7 +1463,7 @@ static bool RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
|
|||||||
|
|
||||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||||
// Prefer XInput over WGI because it allows rumble in the background
|
// Prefer XInput over WGI because it allows rumble in the background
|
||||||
if (!rumbled && ctx->xinput_correlated) {
|
if (!rumbled && ctx->xinput_correlated && !ctx->triggers_rumbling) {
|
||||||
XINPUT_VIBRATION XVibration;
|
XINPUT_VIBRATION XVibration;
|
||||||
|
|
||||||
if (!XINPUTSETSTATE) {
|
if (!XINPUTSETSTATE) {
|
||||||
@@ -1477,12 +1481,12 @@ static bool RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
|
|||||||
#endif // SDL_JOYSTICK_RAWINPUT_XINPUT
|
#endif // SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||||
|
// Save off the motor state in case trigger rumble is started
|
||||||
|
ctx->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
|
||||||
|
ctx->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
|
||||||
if (!rumbled && ctx->wgi_correlated) {
|
if (!rumbled && ctx->wgi_correlated) {
|
||||||
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
|
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
|
||||||
HRESULT hr;
|
HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, ctx->vibration);
|
||||||
gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
|
|
||||||
gamepad_state->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
|
|
||||||
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
rumbled = true;
|
rumbled = true;
|
||||||
}
|
}
|
||||||
@@ -1504,15 +1508,15 @@ static bool RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_
|
|||||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||||
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
|
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
|
||||||
|
|
||||||
|
ctx->vibration.LeftTrigger = (DOUBLE)left_rumble / SDL_MAX_UINT16;
|
||||||
|
ctx->vibration.RightTrigger = (DOUBLE)right_rumble / SDL_MAX_UINT16;
|
||||||
if (ctx->wgi_correlated) {
|
if (ctx->wgi_correlated) {
|
||||||
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
|
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
|
||||||
HRESULT hr;
|
HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, ctx->vibration);
|
||||||
gamepad_state->vibration.LeftTrigger = (DOUBLE)left_rumble / SDL_MAX_UINT16;
|
|
||||||
gamepad_state->vibration.RightTrigger = (DOUBLE)right_rumble / SDL_MAX_UINT16;
|
|
||||||
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
|
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr)) {
|
||||||
return SDL_SetError("Setting vibration failed: 0x%lx", hr);
|
return SDL_SetError("Setting vibration failed: 0x%lx", hr);
|
||||||
}
|
}
|
||||||
|
ctx->triggers_rumbling = (left_rumble > 0 || right_rumble > 0);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return SDL_SetError("Controller isn't correlated yet, try hitting a button first");
|
return SDL_SetError("Controller isn't correlated yet, try hitting a button first");
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
+93
-102
@@ -213,93 +213,91 @@ static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd)
|
|||||||
SDL_Log("Render commands to flush:");
|
SDL_Log("Render commands to flush:");
|
||||||
while (cmd) {
|
while (cmd) {
|
||||||
switch (cmd->command) {
|
switch (cmd->command) {
|
||||||
case SDL_RENDERCMD_NO_OP:
|
case SDL_RENDERCMD_NO_OP:
|
||||||
SDL_Log(" %u. no-op", i++);
|
SDL_Log(" %u. no-op", i++);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_SETVIEWPORT:
|
case SDL_RENDERCMD_SETVIEWPORT:
|
||||||
SDL_Log(" %u. set viewport (first=%u, rect={(%d, %d), %dx%d})", i++,
|
SDL_Log(" %u. set viewport (first=%u, rect={(%d, %d), %dx%d})", i++,
|
||||||
(unsigned int) cmd->data.viewport.first,
|
(unsigned int)cmd->data.viewport.first,
|
||||||
cmd->data.viewport.rect.x, cmd->data.viewport.rect.y,
|
cmd->data.viewport.rect.x, cmd->data.viewport.rect.y,
|
||||||
cmd->data.viewport.rect.w, cmd->data.viewport.rect.h);
|
cmd->data.viewport.rect.w, cmd->data.viewport.rect.h);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_SETCLIPRECT:
|
case SDL_RENDERCMD_SETCLIPRECT:
|
||||||
SDL_Log(" %u. set cliprect (enabled=%s, rect={(%d, %d), %dx%d})", i++,
|
SDL_Log(" %u. set cliprect (enabled=%s, rect={(%d, %d), %dx%d})", i++,
|
||||||
cmd->data.cliprect.enabled ? "true" : "false",
|
cmd->data.cliprect.enabled ? "true" : "false",
|
||||||
cmd->data.cliprect.rect.x, cmd->data.cliprect.rect.y,
|
cmd->data.cliprect.rect.x, cmd->data.cliprect.rect.y,
|
||||||
cmd->data.cliprect.rect.w, cmd->data.cliprect.rect.h);
|
cmd->data.cliprect.rect.w, cmd->data.cliprect.rect.h);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_SETDRAWCOLOR:
|
case SDL_RENDERCMD_SETDRAWCOLOR:
|
||||||
SDL_Log(" %u. set draw color (first=%u, r=%d, g=%d, b=%d, a=%d, color_scale=%g)", i++,
|
SDL_Log(" %u. set draw color (first=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, color_scale=%g)", i++,
|
||||||
(unsigned int) cmd->data.color.first,
|
(unsigned int)cmd->data.color.first,
|
||||||
(int) cmd->data.color.color.r, (int) cmd->data.color.color.g,
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
(int) cmd->data.color.color.b, (int) cmd->data.color.color.a, cmd->data.color.color_scale);
|
cmd->data.draw.color.b, cmd->data.draw.color.a, cmd->data.color.color_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_CLEAR:
|
case SDL_RENDERCMD_CLEAR:
|
||||||
SDL_Log(" %u. clear (first=%u, r=%d, g=%d, b=%d, a=%d, color_scale=%g)", i++,
|
SDL_Log(" %u. clear (first=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, color_scale=%g)", i++,
|
||||||
(unsigned int) cmd->data.color.first,
|
(unsigned int)cmd->data.color.first,
|
||||||
(int) cmd->data.color.color.r, (int) cmd->data.color.color.g,
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
(int) cmd->data.color.color.b, (int) cmd->data.color.color.a, cmd->data.color.color_scale);
|
cmd->data.draw.color.b, cmd->data.draw.color.a, cmd->data.color.color_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_DRAW_POINTS:
|
case SDL_RENDERCMD_DRAW_POINTS:
|
||||||
SDL_Log(" %u. draw points (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++,
|
SDL_Log(" %u. draw points (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g)", i++,
|
||||||
(unsigned int) cmd->data.draw.first,
|
(unsigned int)cmd->data.draw.first,
|
||||||
(unsigned int) cmd->data.draw.count,
|
(unsigned int)cmd->data.draw.count,
|
||||||
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
|
cmd->data.draw.color.b, cmd->data.draw.color.a,
|
||||||
(int) cmd->data.draw.blend, cmd->data.draw.color_scale);
|
(int)cmd->data.draw.blend, cmd->data.draw.color_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_DRAW_LINES:
|
case SDL_RENDERCMD_DRAW_LINES:
|
||||||
SDL_Log(" %u. draw lines (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++,
|
SDL_Log(" %u. draw lines (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g)", i++,
|
||||||
(unsigned int) cmd->data.draw.first,
|
(unsigned int)cmd->data.draw.first,
|
||||||
(unsigned int) cmd->data.draw.count,
|
(unsigned int)cmd->data.draw.count,
|
||||||
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
|
cmd->data.draw.color.b, cmd->data.draw.color.a,
|
||||||
(int) cmd->data.draw.blend, cmd->data.draw.color_scale);
|
(int)cmd->data.draw.blend, cmd->data.draw.color_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_FILL_RECTS:
|
case SDL_RENDERCMD_FILL_RECTS:
|
||||||
SDL_Log(" %u. fill rects (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++,
|
SDL_Log(" %u. fill rects (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g)", i++,
|
||||||
(unsigned int) cmd->data.draw.first,
|
(unsigned int)cmd->data.draw.first,
|
||||||
(unsigned int) cmd->data.draw.count,
|
(unsigned int)cmd->data.draw.count,
|
||||||
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
|
cmd->data.draw.color.b, cmd->data.draw.color.a,
|
||||||
(int) cmd->data.draw.blend, cmd->data.draw.color_scale);
|
(int)cmd->data.draw.blend, cmd->data.draw.color_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_COPY:
|
case SDL_RENDERCMD_COPY:
|
||||||
SDL_Log(" %u. copy (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++,
|
SDL_Log(" %u. copy (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g, tex=%p)", i++,
|
||||||
(unsigned int) cmd->data.draw.first,
|
(unsigned int)cmd->data.draw.first,
|
||||||
(unsigned int) cmd->data.draw.count,
|
(unsigned int)cmd->data.draw.count,
|
||||||
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
|
cmd->data.draw.color.b, cmd->data.draw.color.a,
|
||||||
(int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
|
(int)cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_RENDERCMD_COPY_EX:
|
||||||
|
SDL_Log(" %u. copyex (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g, tex=%p)", i++,
|
||||||
|
(unsigned int)cmd->data.draw.first,
|
||||||
|
(unsigned int)cmd->data.draw.count,
|
||||||
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
|
cmd->data.draw.color.b, cmd->data.draw.color.a,
|
||||||
|
(int)cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
|
||||||
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_COPY_EX:
|
case SDL_RENDERCMD_GEOMETRY:
|
||||||
SDL_Log(" %u. copyex (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++,
|
SDL_Log(" %u. geometry (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g, tex=%p)", i++,
|
||||||
(unsigned int) cmd->data.draw.first,
|
(unsigned int)cmd->data.draw.first,
|
||||||
(unsigned int) cmd->data.draw.count,
|
(unsigned int)cmd->data.draw.count,
|
||||||
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
|
cmd->data.draw.color.r, cmd->data.draw.color.g,
|
||||||
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
|
cmd->data.draw.color.b, cmd->data.draw.color.a,
|
||||||
(int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
|
(int)cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_RENDERCMD_GEOMETRY:
|
|
||||||
SDL_Log(" %u. geometry (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++,
|
|
||||||
(unsigned int) cmd->data.draw.first,
|
|
||||||
(unsigned int) cmd->data.draw.count,
|
|
||||||
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
|
|
||||||
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
|
|
||||||
(int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
cmd = cmd->next;
|
cmd = cmd->next;
|
||||||
}
|
}
|
||||||
@@ -462,8 +460,8 @@ static void UpdatePixelClipRect(SDL_Renderer *renderer, SDL_RenderViewState *vie
|
|||||||
{
|
{
|
||||||
const float scale_x = view->current_scale.x;
|
const float scale_x = view->current_scale.x;
|
||||||
const float scale_y = view->current_scale.y;
|
const float scale_y = view->current_scale.y;
|
||||||
view->pixel_clip_rect.x = (int)SDL_floorf((view->clip_rect.x * scale_x) + view->logical_offset.x);
|
view->pixel_clip_rect.x = (int)SDL_floorf(view->clip_rect.x * scale_x);
|
||||||
view->pixel_clip_rect.y = (int)SDL_floorf((view->clip_rect.y * scale_y) + view->logical_offset.y);
|
view->pixel_clip_rect.y = (int)SDL_floorf(view->clip_rect.y * scale_y);
|
||||||
view->pixel_clip_rect.w = (int)SDL_ceilf(view->clip_rect.w * scale_x);
|
view->pixel_clip_rect.w = (int)SDL_ceilf(view->clip_rect.w * scale_x);
|
||||||
view->pixel_clip_rect.h = (int)SDL_ceilf(view->clip_rect.h * scale_y);
|
view->pixel_clip_rect.h = (int)SDL_ceilf(view->clip_rect.h * scale_y);
|
||||||
}
|
}
|
||||||
@@ -573,6 +571,9 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
|
|||||||
cmd->data.draw.color = *color;
|
cmd->data.draw.color = *color;
|
||||||
cmd->data.draw.blend = blendMode;
|
cmd->data.draw.blend = blendMode;
|
||||||
cmd->data.draw.texture = texture;
|
cmd->data.draw.texture = texture;
|
||||||
|
if (texture) {
|
||||||
|
cmd->data.draw.texture_scale_mode = texture->scaleMode;
|
||||||
|
}
|
||||||
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
|
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -827,6 +828,10 @@ static bool SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
|||||||
SDL_Renderer *renderer = (SDL_Renderer *)userdata;
|
SDL_Renderer *renderer = (SDL_Renderer *)userdata;
|
||||||
SDL_Window *window = renderer->window;
|
SDL_Window *window = renderer->window;
|
||||||
|
|
||||||
|
if (event->window.windowID != SDL_GetWindowID(window)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (renderer->WindowEvent) {
|
if (renderer->WindowEvent) {
|
||||||
renderer->WindowEvent(renderer, &event->window);
|
renderer->WindowEvent(renderer, &event->window);
|
||||||
}
|
}
|
||||||
@@ -1119,12 +1124,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
|
int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
|
||||||
if (!SDL_SetRenderVSync(renderer, vsync)) {
|
SDL_SetRenderVSync(renderer, vsync);
|
||||||
if (vsync == 0) {
|
|
||||||
// Some renderers require vsync enabled
|
|
||||||
SDL_SetRenderVSync(renderer, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SDL_CalculateSimulatedVSyncInterval(renderer, window);
|
SDL_CalculateSimulatedVSyncInterval(renderer, window);
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
|
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
|
||||||
@@ -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)) {
|
||||||
@@ -1962,8 +1963,6 @@ bool SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode)
|
|||||||
|
|
||||||
bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer;
|
|
||||||
|
|
||||||
CHECK_TEXTURE_MAGIC(texture, false);
|
CHECK_TEXTURE_MAGIC(texture, false);
|
||||||
|
|
||||||
if (scaleMode != SDL_SCALEMODE_NEAREST &&
|
if (scaleMode != SDL_SCALEMODE_NEAREST &&
|
||||||
@@ -1971,12 +1970,10 @@ bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|||||||
return SDL_InvalidParamError("scaleMode");
|
return SDL_InvalidParamError("scaleMode");
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer = texture->renderer;
|
|
||||||
texture->scaleMode = scaleMode;
|
texture->scaleMode = scaleMode;
|
||||||
|
|
||||||
if (texture->native) {
|
if (texture->native) {
|
||||||
return SDL_SetTextureScaleMode(texture->native, scaleMode);
|
return SDL_SetTextureScaleMode(texture->native, scaleMode);
|
||||||
} else {
|
|
||||||
renderer->SetTextureScaleMode(renderer, texture, scaleMode);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2576,7 +2573,7 @@ static void UpdateLogicalPresentation(SDL_Renderer *renderer)
|
|||||||
const float logical_h = view->logical_h;
|
const float logical_h = view->logical_h;
|
||||||
int iwidth, iheight;
|
int iwidth, iheight;
|
||||||
|
|
||||||
if (renderer->target) {
|
if (!is_main_view && renderer->target) {
|
||||||
iwidth = (int)renderer->target->w;
|
iwidth = (int)renderer->target->w;
|
||||||
iheight = (int)renderer->target->h;
|
iheight = (int)renderer->target->h;
|
||||||
} else {
|
} else {
|
||||||
@@ -3934,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5493,7 +5489,8 @@ bool SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!renderer->SetVSync) {
|
if (!renderer->SetVSync ||
|
||||||
|
!renderer->SetVSync(renderer, vsync)) {
|
||||||
switch (vsync) {
|
switch (vsync) {
|
||||||
case 0:
|
case 0:
|
||||||
renderer->simulate_vsync = false;
|
renderer->simulate_vsync = false;
|
||||||
@@ -5504,12 +5501,6 @@ bool SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync)
|
|||||||
default:
|
default:
|
||||||
return SDL_Unsupported();
|
return SDL_Unsupported();
|
||||||
}
|
}
|
||||||
} else if (!renderer->SetVSync(renderer, vsync)) {
|
|
||||||
if (vsync == 1) {
|
|
||||||
renderer->simulate_vsync = true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_VSYNC_NUMBER, vsync);
|
SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_VSYNC_NUMBER, vsync);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef enum SDL_TextureAddressMode
|
typedef enum SDL_TextureAddressMode
|
||||||
{
|
{
|
||||||
|
SDL_TEXTURE_ADDRESS_INVALID = -1,
|
||||||
SDL_TEXTURE_ADDRESS_AUTO,
|
SDL_TEXTURE_ADDRESS_AUTO,
|
||||||
SDL_TEXTURE_ADDRESS_CLAMP,
|
SDL_TEXTURE_ADDRESS_CLAMP,
|
||||||
SDL_TEXTURE_ADDRESS_WRAP,
|
SDL_TEXTURE_ADDRESS_WRAP,
|
||||||
@@ -155,6 +156,7 @@ typedef struct SDL_RenderCommand
|
|||||||
SDL_FColor color;
|
SDL_FColor color;
|
||||||
SDL_BlendMode blend;
|
SDL_BlendMode blend;
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
|
SDL_ScaleMode texture_scale_mode;
|
||||||
SDL_TextureAddressMode texture_address_mode;
|
SDL_TextureAddressMode texture_address_mode;
|
||||||
} draw;
|
} draw;
|
||||||
struct
|
struct
|
||||||
@@ -224,7 +226,6 @@ struct SDL_Renderer
|
|||||||
bool (*LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
|
bool (*LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||||
const SDL_Rect *rect, void **pixels, int *pitch);
|
const SDL_Rect *rect, void **pixels, int *pitch);
|
||||||
void (*UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture);
|
void (*UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||||
void (*SetTextureScaleMode)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode);
|
|
||||||
bool (*SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture);
|
bool (*SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||||
SDL_Surface *(*RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect);
|
SDL_Surface *(*RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect);
|
||||||
bool (*RenderPresent)(SDL_Renderer *renderer);
|
bool (*RenderPresent)(SDL_Renderer *renderer);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ typedef struct
|
|||||||
bool updateSize;
|
bool updateSize;
|
||||||
bool beginScene;
|
bool beginScene;
|
||||||
bool enableSeparateAlphaBlend;
|
bool enableSeparateAlphaBlend;
|
||||||
D3DTEXTUREFILTERTYPE scaleMode[3];
|
SDL_ScaleMode scaleMode[3];
|
||||||
SDL_TextureAddressMode addressMode[3];
|
SDL_TextureAddressMode addressMode[3];
|
||||||
IDirect3DSurface9 *defaultRenderTarget;
|
IDirect3DSurface9 *defaultRenderTarget;
|
||||||
IDirect3DSurface9 *currentRenderTarget;
|
IDirect3DSurface9 *currentRenderTarget;
|
||||||
@@ -89,7 +89,6 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
D3D_TextureRep texture;
|
D3D_TextureRep texture;
|
||||||
D3DTEXTUREFILTERTYPE scaleMode;
|
|
||||||
D3D9_Shader shader;
|
D3D9_Shader shader;
|
||||||
const float *shader_params;
|
const float *shader_params;
|
||||||
|
|
||||||
@@ -274,10 +273,14 @@ static void D3D_InitRenderState(D3D_RenderData *data)
|
|||||||
IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
|
IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
|
||||||
|
|
||||||
// Reset our current scale mode
|
// Reset our current scale mode
|
||||||
SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
|
for (int i = 0; i < SDL_arraysize(data->scaleMode); ++i) {
|
||||||
|
data->scaleMode[i] = SDL_SCALEMODE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset our current address mode
|
// Reset our current address mode
|
||||||
SDL_zeroa(data->addressMode);
|
for (int i = 0; i < SDL_arraysize(data->addressMode); ++i) {
|
||||||
|
data->addressMode[i] = SDL_TEXTURE_ADDRESS_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
// Start the render with beginScene
|
// Start the render with beginScene
|
||||||
data->beginScene = true;
|
data->beginScene = true;
|
||||||
@@ -533,7 +536,6 @@ static bool D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
|||||||
if (!texturedata) {
|
if (!texturedata) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
texturedata->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
|
|
||||||
|
|
||||||
texture->internal = texturedata;
|
texture->internal = texturedata;
|
||||||
|
|
||||||
@@ -736,17 +738,6 @@ static void D3D_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void D3D_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
|
||||||
|
|
||||||
if (!texturedata) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
texturedata->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool D3D_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool D3D_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||||
@@ -926,12 +917,22 @@ static bool BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DW
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
|
static void UpdateTextureScaleMode(D3D_RenderData *data, SDL_ScaleMode scaleMode, unsigned index)
|
||||||
{
|
{
|
||||||
if (texturedata->scaleMode != data->scaleMode[index]) {
|
if (scaleMode != data->scaleMode[index]) {
|
||||||
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, texturedata->scaleMode);
|
switch (scaleMode) {
|
||||||
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, texturedata->scaleMode);
|
case SDL_SCALEMODE_NEAREST:
|
||||||
data->scaleMode[index] = texturedata->scaleMode;
|
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||||
|
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||||
|
break;
|
||||||
|
case SDL_SCALEMODE_LINEAR:
|
||||||
|
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||||
|
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data->scaleMode[index] = scaleMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -954,7 +955,7 @@ static void UpdateTextureAddressMode(D3D_RenderData *data, SDL_TextureAddressMod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_TextureAddressMode addressMode, D3D9_Shader *shader, const float **shader_params)
|
static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Shader *shader, const float **shader_params)
|
||||||
{
|
{
|
||||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
||||||
|
|
||||||
@@ -962,9 +963,6 @@ static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_Te
|
|||||||
return SDL_SetError("Texture is not currently available");
|
return SDL_SetError("Texture is not currently available");
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTextureScaleMode(data, texturedata, 0);
|
|
||||||
UpdateTextureAddressMode(data, addressMode, 0);
|
|
||||||
|
|
||||||
*shader = texturedata->shader;
|
*shader = texturedata->shader;
|
||||||
*shader_params = texturedata->shader_params;
|
*shader_params = texturedata->shader_params;
|
||||||
|
|
||||||
@@ -973,11 +971,6 @@ static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_Te
|
|||||||
}
|
}
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
if (texturedata->yuv) {
|
if (texturedata->yuv) {
|
||||||
UpdateTextureScaleMode(data, texturedata, 1);
|
|
||||||
UpdateTextureScaleMode(data, texturedata, 2);
|
|
||||||
UpdateTextureAddressMode(data, addressMode, 1);
|
|
||||||
UpdateTextureAddressMode(data, addressMode, 2);
|
|
||||||
|
|
||||||
if (!BindTextureRep(data->device, &texturedata->utexture, 1)) {
|
if (!BindTextureRep(data->device, &texturedata->utexture, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1005,7 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
|
|||||||
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
|
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (texture && !SetupTextureState(data, texture, cmd->data.draw.texture_address_mode, &shader, &shader_params)) {
|
if (texture && !SetupTextureState(data, texture, &shader, &shader_params)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1040,13 +1033,30 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
|
|||||||
data->drawstate.texture = texture;
|
data->drawstate.texture = texture;
|
||||||
} else if (texture) {
|
} else if (texture) {
|
||||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
||||||
UpdateDirtyTexture(data->device, &texturedata->texture);
|
if (texturedata) {
|
||||||
|
UpdateDirtyTexture(data->device, &texturedata->texture);
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
if (texturedata->yuv) {
|
if (texturedata->yuv) {
|
||||||
UpdateDirtyTexture(data->device, &texturedata->utexture);
|
UpdateDirtyTexture(data->device, &texturedata->utexture);
|
||||||
UpdateDirtyTexture(data->device, &texturedata->vtexture);
|
UpdateDirtyTexture(data->device, &texturedata->vtexture);
|
||||||
|
}
|
||||||
|
#endif // SDL_HAVE_YUV
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
if (texture) {
|
||||||
|
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 0);
|
||||||
|
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 0);
|
||||||
|
|
||||||
|
#ifdef SDL_HAVE_YUV
|
||||||
|
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
||||||
|
if (texturedata && texturedata->yuv) {
|
||||||
|
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 1);
|
||||||
|
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 2);
|
||||||
|
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 1);
|
||||||
|
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 2);
|
||||||
|
}
|
||||||
|
#endif // SDL_HAVE_YUV
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blend != data->drawstate.blend) {
|
if (blend != data->drawstate.blend) {
|
||||||
@@ -1653,7 +1663,6 @@ static bool D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = D3D_LockTexture;
|
renderer->LockTexture = D3D_LockTexture;
|
||||||
renderer->UnlockTexture = D3D_UnlockTexture;
|
renderer->UnlockTexture = D3D_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = D3D_SetRenderTarget;
|
renderer->SetRenderTarget = D3D_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = D3D_QueueNoOp;
|
renderer->QueueSetViewport = D3D_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = D3D_QueueNoOp;
|
renderer->QueueSetDrawColor = D3D_QueueNoOp;
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ typedef struct
|
|||||||
ID3D11Texture2D *stagingTexture;
|
ID3D11Texture2D *stagingTexture;
|
||||||
int lockedTexturePositionX;
|
int lockedTexturePositionX;
|
||||||
int lockedTexturePositionY;
|
int lockedTexturePositionY;
|
||||||
D3D11_FILTER scaleMode;
|
|
||||||
D3D11_Shader shader;
|
D3D11_Shader shader;
|
||||||
const float *YCbCr_matrix;
|
const float *YCbCr_matrix;
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
@@ -1172,7 +1171,6 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
if (!textureData) {
|
if (!textureData) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
|
|
||||||
texture->internal = textureData;
|
texture->internal = textureData;
|
||||||
|
|
||||||
@@ -1796,17 +1794,6 @@ static void D3D11_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
SAFE_RELEASE(textureData->stagingTexture);
|
SAFE_RELEASE(textureData->stagingTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->internal;
|
|
||||||
|
|
||||||
if (!textureData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
|
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
|
||||||
@@ -2318,8 +2305,8 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
|
|||||||
|
|
||||||
D3D11_SetupShaderConstants(renderer, cmd, texture, &constants);
|
D3D11_SetupShaderConstants(renderer, cmd, texture, &constants);
|
||||||
|
|
||||||
switch (textureData->scaleMode) {
|
switch (cmd->data.draw.texture_scale_mode) {
|
||||||
case D3D11_FILTER_MIN_MAG_MIP_POINT:
|
case SDL_SCALEMODE_NEAREST:
|
||||||
switch (cmd->data.draw.texture_address_mode) {
|
switch (cmd->data.draw.texture_address_mode) {
|
||||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
textureSampler = rendererData->samplers[D3D11_SAMPLER_NEAREST_CLAMP];
|
textureSampler = rendererData->samplers[D3D11_SAMPLER_NEAREST_CLAMP];
|
||||||
@@ -2331,7 +2318,7 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
|
|||||||
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
|
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case D3D11_FILTER_MIN_MAG_MIP_LINEAR:
|
case SDL_SCALEMODE_LINEAR:
|
||||||
switch (cmd->data.draw.texture_address_mode) {
|
switch (cmd->data.draw.texture_address_mode) {
|
||||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
textureSampler = rendererData->samplers[D3D11_SAMPLER_LINEAR_CLAMP];
|
textureSampler = rendererData->samplers[D3D11_SAMPLER_LINEAR_CLAMP];
|
||||||
@@ -2344,7 +2331,7 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
|
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
|
||||||
}
|
}
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
if (textureData->yuv) {
|
if (textureData->yuv) {
|
||||||
@@ -2712,7 +2699,6 @@ static bool D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = D3D11_LockTexture;
|
renderer->LockTexture = D3D11_LockTexture;
|
||||||
renderer->UnlockTexture = D3D11_UnlockTexture;
|
renderer->UnlockTexture = D3D11_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = D3D11_SetRenderTarget;
|
renderer->SetRenderTarget = D3D11_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = D3D11_QueueNoOp;
|
renderer->QueueSetViewport = D3D11_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = D3D11_QueueNoOp;
|
renderer->QueueSetDrawColor = D3D11_QueueNoOp;
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ typedef struct
|
|||||||
DXGI_FORMAT mainTextureFormat;
|
DXGI_FORMAT mainTextureFormat;
|
||||||
ID3D12Resource *stagingBuffer;
|
ID3D12Resource *stagingBuffer;
|
||||||
D3D12_RESOURCE_STATES stagingResourceState;
|
D3D12_RESOURCE_STATES stagingResourceState;
|
||||||
D3D12_FILTER scaleMode;
|
|
||||||
D3D12_Shader shader;
|
D3D12_Shader shader;
|
||||||
const float *YCbCr_matrix;
|
const float *YCbCr_matrix;
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
@@ -1574,7 +1573,6 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
if (!textureData) {
|
if (!textureData) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
|
|
||||||
texture->internal = textureData;
|
texture->internal = textureData;
|
||||||
textureData->mainTextureFormat = textureFormat;
|
textureData->mainTextureFormat = textureFormat;
|
||||||
@@ -1992,6 +1990,10 @@ static bool D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SDL_HAVE_YUV
|
#endif // SDL_HAVE_YUV
|
||||||
|
if (textureData->mainTextureResourceView.ptr == rendererData->currentShaderResource.ptr) {
|
||||||
|
// We'll need to rebind this resource after updating it
|
||||||
|
rendererData->currentShaderResource.ptr = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2018,6 +2020,10 @@ static bool D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
|||||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV)) {
|
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (textureData->mainTextureResourceView.ptr == rendererData->currentShaderResource.ptr) {
|
||||||
|
// We'll need to rebind this resource after updating it
|
||||||
|
rendererData->currentShaderResource.ptr = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2036,10 +2042,13 @@ static bool D3D12_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
|
|||||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState)) {
|
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, UVplane, UVpitch, &textureData->mainResourceState)) {
|
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, UVplane, UVpitch, &textureData->mainResourceState)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (textureData->mainTextureResourceView.ptr == rendererData->currentShaderResource.ptr) {
|
||||||
|
// We'll need to rebind this resource after updating it
|
||||||
|
rendererData->currentShaderResource.ptr = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2244,17 +2253,6 @@ static void D3D12_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
D3D_SAFE_RELEASE(textureData->stagingBuffer);
|
D3D_SAFE_RELEASE(textureData->stagingBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->internal;
|
|
||||||
|
|
||||||
if (!textureData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->internal;
|
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->internal;
|
||||||
@@ -2745,8 +2743,8 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
|
|||||||
|
|
||||||
D3D12_SetupShaderConstants(renderer, cmd, texture, &constants);
|
D3D12_SetupShaderConstants(renderer, cmd, texture, &constants);
|
||||||
|
|
||||||
switch (textureData->scaleMode) {
|
switch (cmd->data.draw.texture_scale_mode) {
|
||||||
case D3D12_FILTER_MIN_MAG_MIP_POINT:
|
case SDL_SCALEMODE_NEAREST:
|
||||||
switch (cmd->data.draw.texture_address_mode) {
|
switch (cmd->data.draw.texture_address_mode) {
|
||||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
textureSampler = &rendererData->samplers[D3D12_SAMPLER_NEAREST_CLAMP];
|
textureSampler = &rendererData->samplers[D3D12_SAMPLER_NEAREST_CLAMP];
|
||||||
@@ -2758,7 +2756,7 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
|
|||||||
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
|
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case D3D12_FILTER_MIN_MAG_MIP_LINEAR:
|
case SDL_SCALEMODE_LINEAR:
|
||||||
switch (cmd->data.draw.texture_address_mode) {
|
switch (cmd->data.draw.texture_address_mode) {
|
||||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
textureSampler = &rendererData->samplers[D3D12_SAMPLER_LINEAR_CLAMP];
|
textureSampler = &rendererData->samplers[D3D12_SAMPLER_LINEAR_CLAMP];
|
||||||
@@ -2771,7 +2769,7 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
|
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
|
||||||
}
|
}
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
if (textureData->yuv) {
|
if (textureData->yuv) {
|
||||||
@@ -3248,7 +3246,6 @@ bool D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Proper
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = D3D12_LockTexture;
|
renderer->LockTexture = D3D12_LockTexture;
|
||||||
renderer->UnlockTexture = D3D12_UnlockTexture;
|
renderer->UnlockTexture = D3D12_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = D3D12_SetRenderTarget;
|
renderer->SetRenderTarget = D3D12_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = D3D12_QueueNoOp;
|
renderer->QueueSetViewport = D3D12_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = D3D12_QueueNoOp;
|
renderer->QueueSetDrawColor = D3D12_QueueNoOp;
|
||||||
|
|||||||
@@ -335,11 +335,6 @@ static void GPU_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
GPU_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
|
GPU_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GPU_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scale_mode)
|
|
||||||
{
|
|
||||||
// nothing to do in this backend.
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool GPU_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool GPU_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
|
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
|
||||||
@@ -450,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,8 +488,7 @@ static void PushUniforms(GPU_RenderData *data, SDL_RenderCommand *cmd)
|
|||||||
SDL_PushGPUVertexUniformData(data->state.command_buffer, 0, &uniforms, sizeof(uniforms));
|
SDL_PushGPUVertexUniformData(data->state.command_buffer, 0, &uniforms, sizeof(uniforms));
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_GPUSampler **SamplerPointer(
|
static SDL_GPUSampler **SamplerPointer(GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
|
||||||
GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
|
|
||||||
{
|
{
|
||||||
return &data->samplers[scale_mode][address_mode - 1];
|
return &data->samplers[scale_mode][address_mode - 1];
|
||||||
}
|
}
|
||||||
@@ -575,7 +568,7 @@ static void Draw(
|
|||||||
if (tdata) {
|
if (tdata) {
|
||||||
SDL_GPUTextureSamplerBinding sampler_bind;
|
SDL_GPUTextureSamplerBinding sampler_bind;
|
||||||
SDL_zero(sampler_bind);
|
SDL_zero(sampler_bind);
|
||||||
sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture->scaleMode);
|
sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture_scale_mode);
|
||||||
sampler_bind.texture = tdata->texture;
|
sampler_bind.texture = tdata->texture;
|
||||||
SDL_BindGPUFragmentSamplers(pass, 0, &sampler_bind, 1);
|
SDL_BindGPUFragmentSamplers(pass, 0, &sampler_bind, 1);
|
||||||
}
|
}
|
||||||
@@ -785,6 +778,8 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
same texture, we can combine them all into a single draw call. */
|
same texture, we can combine them all into a single draw call. */
|
||||||
SDL_Texture *thistexture = cmd->data.draw.texture;
|
SDL_Texture *thistexture = cmd->data.draw.texture;
|
||||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||||
|
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
|
||||||
|
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode;
|
||||||
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
||||||
SDL_RenderCommand *finalcmd = cmd;
|
SDL_RenderCommand *finalcmd = cmd;
|
||||||
SDL_RenderCommand *nextcmd = cmd->next;
|
SDL_RenderCommand *nextcmd = cmd->next;
|
||||||
@@ -795,7 +790,10 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||||
if (nextcmdtype != thiscmdtype) {
|
if (nextcmdtype != thiscmdtype) {
|
||||||
break; // can't go any further on this draw call, different render command up next.
|
break; // can't go any further on this draw call, different render command up next.
|
||||||
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
|
} else if (nextcmd->data.draw.texture != thistexture ||
|
||||||
|
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
|
||||||
|
nextcmd->data.draw.texture_address_mode != thisaddressmode ||
|
||||||
|
nextcmd->data.draw.blend != thisblend) {
|
||||||
// FIXME should we check address mode too?
|
// FIXME should we check address mode too?
|
||||||
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
||||||
} else {
|
} else {
|
||||||
@@ -1176,7 +1174,6 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
|||||||
renderer->UpdateTexture = GPU_UpdateTexture;
|
renderer->UpdateTexture = GPU_UpdateTexture;
|
||||||
renderer->LockTexture = GPU_LockTexture;
|
renderer->LockTexture = GPU_LockTexture;
|
||||||
renderer->UnlockTexture = GPU_UnlockTexture;
|
renderer->UnlockTexture = GPU_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = GPU_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = GPU_SetRenderTarget;
|
renderer->SetRenderTarget = GPU_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = GPU_QueueNoOp;
|
renderer->QueueSetViewport = GPU_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = GPU_QueueNoOp;
|
renderer->QueueSetDrawColor = GPU_QueueNoOp;
|
||||||
|
|||||||
@@ -79,15 +79,10 @@ static const size_t CONSTANTS_OFFSET_DECODE_BT2020_LIMITED = ALIGN_CONSTANTS(16,
|
|||||||
static const size_t CONSTANTS_OFFSET_DECODE_BT2020_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT2020_LIMITED + sizeof(float) * 4 * 4);
|
static const size_t CONSTANTS_OFFSET_DECODE_BT2020_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT2020_LIMITED + sizeof(float) * 4 * 4);
|
||||||
static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT2020_FULL + sizeof(float) * 4 * 4;
|
static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT2020_FULL + sizeof(float) * 4 * 4;
|
||||||
|
|
||||||
// Sampler types
|
#define RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v) \
|
||||||
typedef enum
|
(((scale_mode == SDL_SCALEMODE_NEAREST) << 0) | \
|
||||||
{
|
((address_u == SDL_TEXTURE_ADDRESS_WRAP) << 1) | \
|
||||||
SDL_METAL_SAMPLER_NEAREST_CLAMP,
|
((address_v == SDL_TEXTURE_ADDRESS_WRAP) << 2))
|
||||||
SDL_METAL_SAMPLER_NEAREST_WRAP,
|
|
||||||
SDL_METAL_SAMPLER_LINEAR_CLAMP,
|
|
||||||
SDL_METAL_SAMPLER_LINEAR_WRAP,
|
|
||||||
SDL_NUM_METAL_SAMPLERS
|
|
||||||
} SDL_METAL_sampler_type;
|
|
||||||
|
|
||||||
typedef enum SDL_MetalVertexFunction
|
typedef enum SDL_MetalVertexFunction
|
||||||
{
|
{
|
||||||
@@ -139,7 +134,7 @@ typedef struct METAL_ShaderPipelines
|
|||||||
@property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
|
@property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
|
||||||
@property(nonatomic, retain) id<MTLLibrary> mtllibrary;
|
@property(nonatomic, retain) id<MTLLibrary> mtllibrary;
|
||||||
@property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
|
@property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
|
||||||
@property(nonatomic, retain) NSMutableArray<id<MTLSamplerState>> *mtlsamplers;
|
@property(nonatomic, retain) NSMutableDictionary<NSNumber *, id<MTLSamplerState>> *mtlsamplers;
|
||||||
@property(nonatomic, retain) id<MTLBuffer> mtlbufconstants;
|
@property(nonatomic, retain) id<MTLBuffer> mtlbufconstants;
|
||||||
@property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices;
|
@property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices;
|
||||||
@property(nonatomic, assign) SDL_MetalView mtlview;
|
@property(nonatomic, assign) SDL_MetalView mtlview;
|
||||||
@@ -1070,10 +1065,6 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void METAL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
@@ -1299,6 +1290,9 @@ typedef struct
|
|||||||
__unsafe_unretained id<MTLBuffer> vertex_buffer;
|
__unsafe_unretained id<MTLBuffer> vertex_buffer;
|
||||||
size_t constants_offset;
|
size_t constants_offset;
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
|
SDL_ScaleMode texture_scale_mode;
|
||||||
|
SDL_TextureAddressMode texture_address_mode_u;
|
||||||
|
SDL_TextureAddressMode texture_address_mode_v;
|
||||||
bool cliprect_dirty;
|
bool cliprect_dirty;
|
||||||
bool cliprect_enabled;
|
bool cliprect_enabled;
|
||||||
SDL_Rect cliprect;
|
SDL_Rect cliprect;
|
||||||
@@ -1456,6 +1450,58 @@ static bool SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static id<MTLSamplerState> GetSampler(SDL3METAL_RenderData *data, SDL_ScaleMode scale_mode, SDL_TextureAddressMode address_u, SDL_TextureAddressMode address_v)
|
||||||
|
{
|
||||||
|
NSNumber *key = [NSNumber numberWithInteger:RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v)];
|
||||||
|
id<MTLSamplerState> mtlsampler = data.mtlsamplers[key];
|
||||||
|
if (mtlsampler == nil) {
|
||||||
|
MTLSamplerDescriptor *samplerdesc;
|
||||||
|
samplerdesc = [[MTLSamplerDescriptor alloc] init];
|
||||||
|
switch (scale_mode) {
|
||||||
|
case SDL_SCALEMODE_NEAREST:
|
||||||
|
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
|
||||||
|
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
|
||||||
|
break;
|
||||||
|
case SDL_SCALEMODE_LINEAR:
|
||||||
|
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
|
||||||
|
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SDL_SetError("Unknown scale mode: %d", scale_mode);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
switch (address_u) {
|
||||||
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
|
samplerdesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||||
|
break;
|
||||||
|
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||||
|
samplerdesc.sAddressMode = MTLSamplerAddressModeRepeat;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SDL_SetError("Unknown texture address mode: %d", address_u);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
switch (address_v) {
|
||||||
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
|
samplerdesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||||
|
break;
|
||||||
|
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||||
|
samplerdesc.tAddressMode = MTLSamplerAddressModeRepeat;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SDL_SetError("Unknown texture address mode: %d", address_v);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
mtlsampler = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||||
|
if (mtlsampler == nil) {
|
||||||
|
SDL_SetError("Couldn't create sampler");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
data.mtlsamplers[key] = mtlsampler;
|
||||||
|
}
|
||||||
|
return mtlsampler;
|
||||||
|
}
|
||||||
|
|
||||||
static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t constants_offset,
|
static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t constants_offset,
|
||||||
id<MTLBuffer> mtlbufvertex, METAL_DrawStateCache *statecache)
|
id<MTLBuffer> mtlbufvertex, METAL_DrawStateCache *statecache)
|
||||||
{
|
{
|
||||||
@@ -1471,33 +1517,6 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (texture != statecache->texture) {
|
if (texture != statecache->texture) {
|
||||||
id<MTLSamplerState> mtlsampler;
|
|
||||||
|
|
||||||
if (texture->scaleMode == SDL_SCALEMODE_NEAREST) {
|
|
||||||
switch (cmd->data.draw.texture_address_mode) {
|
|
||||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
|
||||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP];
|
|
||||||
break;
|
|
||||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
|
||||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_WRAP];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (cmd->data.draw.texture_address_mode) {
|
|
||||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
|
||||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_CLAMP];
|
|
||||||
break;
|
|
||||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
|
||||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_WRAP];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0];
|
|
||||||
|
|
||||||
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0];
|
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0];
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
if (texturedata.yuv || texturedata.nv12) {
|
if (texturedata.yuv || texturedata.nv12) {
|
||||||
@@ -1507,6 +1526,20 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
|
|||||||
#endif
|
#endif
|
||||||
statecache->texture = texture;
|
statecache->texture = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd->data.draw.texture_scale_mode != statecache->texture_scale_mode ||
|
||||||
|
cmd->data.draw.texture_address_mode != statecache->texture_address_mode_u ||
|
||||||
|
cmd->data.draw.texture_address_mode != statecache->texture_address_mode_v) {
|
||||||
|
id<MTLSamplerState> mtlsampler = GetSampler(data, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode, cmd->data.draw.texture_address_mode);
|
||||||
|
if (mtlsampler == nil) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
[data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0];
|
||||||
|
|
||||||
|
statecache->texture_scale_mode = cmd->data.draw.texture_scale_mode;
|
||||||
|
statecache->texture_address_mode_u = cmd->data.draw.texture_address_mode;
|
||||||
|
statecache->texture_address_mode_v = cmd->data.draw.texture_address_mode;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1527,6 +1560,9 @@ static bool METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
|||||||
statecache.vertex_buffer = nil;
|
statecache.vertex_buffer = nil;
|
||||||
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
||||||
statecache.texture = NULL;
|
statecache.texture = NULL;
|
||||||
|
statecache.texture_scale_mode = SDL_SCALEMODE_INVALID;
|
||||||
|
statecache.texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID;
|
||||||
|
statecache.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID;
|
||||||
statecache.shader_constants_dirty = true;
|
statecache.shader_constants_dirty = true;
|
||||||
statecache.cliprect_dirty = true;
|
statecache.cliprect_dirty = true;
|
||||||
statecache.viewport_dirty = true;
|
statecache.viewport_dirty = true;
|
||||||
@@ -1887,7 +1923,6 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
|||||||
int maxtexsize, quadcount = UINT16_MAX / 4;
|
int maxtexsize, quadcount = UINT16_MAX / 4;
|
||||||
UInt16 *indexdata;
|
UInt16 *indexdata;
|
||||||
size_t indicessize = sizeof(UInt16) * quadcount * 6;
|
size_t indicessize = sizeof(UInt16) * quadcount * 6;
|
||||||
MTLSamplerDescriptor *samplerdesc;
|
|
||||||
id<MTLCommandQueue> mtlcmdqueue;
|
id<MTLCommandQueue> mtlcmdqueue;
|
||||||
id<MTLLibrary> mtllibrary;
|
id<MTLLibrary> mtllibrary;
|
||||||
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
|
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
|
||||||
@@ -2047,27 +2082,7 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
|||||||
data.allpipelines = NULL;
|
data.allpipelines = NULL;
|
||||||
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
|
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
|
||||||
|
|
||||||
static struct
|
data.mtlsamplers = [[NSMutableDictionary<NSNumber *, id<MTLSamplerState>> alloc] init];
|
||||||
{
|
|
||||||
MTLSamplerMinMagFilter filter;
|
|
||||||
MTLSamplerAddressMode address;
|
|
||||||
} samplerParams[] = {
|
|
||||||
{ MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeClampToEdge },
|
|
||||||
{ MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeRepeat },
|
|
||||||
{ MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeClampToEdge },
|
|
||||||
{ MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeRepeat },
|
|
||||||
};
|
|
||||||
SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_NUM_METAL_SAMPLERS);
|
|
||||||
|
|
||||||
data.mtlsamplers = [[NSMutableArray<id<MTLSamplerState>> alloc] init];
|
|
||||||
samplerdesc = [[MTLSamplerDescriptor alloc] init];
|
|
||||||
for (int i = 0; i < SDL_arraysize(samplerParams); ++i) {
|
|
||||||
samplerdesc.minFilter = samplerParams[i].filter;
|
|
||||||
samplerdesc.magFilter = samplerParams[i].filter;
|
|
||||||
samplerdesc.sAddressMode = samplerParams[i].address;
|
|
||||||
samplerdesc.tAddressMode = samplerParams[i].address;
|
|
||||||
[data.mtlsamplers addObject:[data.mtldevice newSamplerStateWithDescriptor:samplerdesc]];
|
|
||||||
}
|
|
||||||
|
|
||||||
mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
|
mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
|
||||||
|
|
||||||
@@ -2129,7 +2144,6 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = METAL_LockTexture;
|
renderer->LockTexture = METAL_LockTexture;
|
||||||
renderer->UnlockTexture = METAL_UnlockTexture;
|
renderer->UnlockTexture = METAL_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = METAL_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = METAL_SetRenderTarget;
|
renderer->SetRenderTarget = METAL_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = METAL_QueueSetViewport;
|
renderer->QueueSetViewport = METAL_QueueSetViewport;
|
||||||
renderer->QueueSetDrawColor = METAL_QueueNoOp;
|
renderer->QueueSetDrawColor = METAL_QueueNoOp;
|
||||||
|
|||||||
@@ -137,7 +137,6 @@ typedef struct
|
|||||||
void *pixels;
|
void *pixels;
|
||||||
int pitch;
|
int pitch;
|
||||||
SDL_Rect locked_rect;
|
SDL_Rect locked_rect;
|
||||||
|
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
// YUV texture support
|
// YUV texture support
|
||||||
bool yuv;
|
bool yuv;
|
||||||
@@ -147,7 +146,8 @@ typedef struct
|
|||||||
GLuint vtexture;
|
GLuint vtexture;
|
||||||
bool vtexture_external;
|
bool vtexture_external;
|
||||||
#endif
|
#endif
|
||||||
|
SDL_ScaleMode texture_scale_mode;
|
||||||
|
SDL_TextureAddressMode texture_address_mode;
|
||||||
GL_FBOList *fbo;
|
GL_FBOList *fbo;
|
||||||
} GL_TextureData;
|
} GL_TextureData;
|
||||||
|
|
||||||
@@ -447,7 +447,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
|
|||||||
GLint internalFormat;
|
GLint internalFormat;
|
||||||
GLenum format, type;
|
GLenum format, type;
|
||||||
int texture_w, texture_h;
|
int texture_w, texture_h;
|
||||||
GLenum scaleMode;
|
|
||||||
|
|
||||||
GL_ActivateRenderer(renderer);
|
GL_ActivateRenderer(renderer);
|
||||||
|
|
||||||
@@ -536,11 +535,10 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
|
|||||||
|
|
||||||
data->format = format;
|
data->format = format;
|
||||||
data->formattype = type;
|
data->formattype = type;
|
||||||
scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
|
data->texture_scale_mode = SDL_SCALEMODE_INVALID;
|
||||||
|
data->texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID;
|
||||||
renderdata->glEnable(textype);
|
renderdata->glEnable(textype);
|
||||||
renderdata->glBindTexture(textype, data->texture);
|
renderdata->glBindTexture(textype, data->texture);
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode);
|
|
||||||
#ifdef SDL_PLATFORM_MACOS
|
#ifdef SDL_PLATFORM_MACOS
|
||||||
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
|
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
|
||||||
#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
|
#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
|
||||||
@@ -596,19 +594,11 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderdata->glBindTexture(textype, data->utexture);
|
renderdata->glBindTexture(textype, data->utexture);
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
|
|
||||||
scaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
|
|
||||||
scaleMode);
|
|
||||||
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
|
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
|
||||||
(texture_h + 1) / 2, 0, format, type, NULL);
|
(texture_h + 1) / 2, 0, format, type, NULL);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
|
||||||
|
|
||||||
renderdata->glBindTexture(textype, data->vtexture);
|
renderdata->glBindTexture(textype, data->vtexture);
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
|
|
||||||
scaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
|
|
||||||
scaleMode);
|
|
||||||
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
|
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
|
||||||
(texture_h + 1) / 2, 0, format, type, NULL);
|
(texture_h + 1) / 2, 0, format, type, NULL);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
|
||||||
@@ -625,10 +615,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
|
|||||||
renderdata->glGenTextures(1, &data->utexture);
|
renderdata->glGenTextures(1, &data->utexture);
|
||||||
}
|
}
|
||||||
renderdata->glBindTexture(textype, data->utexture);
|
renderdata->glBindTexture(textype, data->utexture);
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
|
|
||||||
scaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
|
|
||||||
scaleMode);
|
|
||||||
renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2,
|
renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2,
|
||||||
(texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
(texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture);
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture);
|
||||||
@@ -822,38 +808,6 @@ static void GL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
|
GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
|
|
||||||
const GLenum textype = renderdata->textype;
|
|
||||||
GL_TextureData *data = (GL_TextureData *)texture->internal;
|
|
||||||
GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
|
|
||||||
|
|
||||||
renderdata->glBindTexture(textype, data->texture);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
|
|
||||||
#ifdef SDL_HAVE_YUV
|
|
||||||
if (texture->format == SDL_PIXELFORMAT_YV12 ||
|
|
||||||
texture->format == SDL_PIXELFORMAT_IYUV) {
|
|
||||||
renderdata->glBindTexture(textype, data->utexture);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
|
|
||||||
renderdata->glBindTexture(textype, data->vtexture);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
|
||||||
texture->format == SDL_PIXELFORMAT_NV21) {
|
|
||||||
renderdata->glBindTexture(textype, data->utexture);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
GL_RenderData *data = (GL_RenderData *)renderer->internal;
|
GL_RenderData *data = (GL_RenderData *)renderer->internal;
|
||||||
@@ -1120,6 +1074,23 @@ static bool SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, cons
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool SetTextureScaleMode(GL_RenderData *data, GLenum textype, SDL_ScaleMode scaleMode)
|
||||||
|
{
|
||||||
|
switch (scaleMode) {
|
||||||
|
case SDL_SCALEMODE_NEAREST:
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
break;
|
||||||
|
case SDL_SCALEMODE_LINEAR:
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SDL_SetError("Unknown texture scale mode: %d", scaleMode);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
|
static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
|
||||||
{
|
{
|
||||||
switch (addressMode) {
|
switch (addressMode) {
|
||||||
@@ -1140,41 +1111,23 @@ static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_Textu
|
|||||||
static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
|
static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
|
||||||
{
|
{
|
||||||
SDL_Texture *texture = cmd->data.draw.texture;
|
SDL_Texture *texture = cmd->data.draw.texture;
|
||||||
const GL_TextureData *texturedata = (GL_TextureData *)texture->internal;
|
GL_TextureData *texturedata = (GL_TextureData *)texture->internal;
|
||||||
|
const GLenum textype = data->textype;
|
||||||
|
|
||||||
SetDrawState(data, cmd, texturedata->shader, texturedata->shader_params);
|
SetDrawState(data, cmd, texturedata->shader, texturedata->shader_params);
|
||||||
|
|
||||||
if (texture != data->drawstate.texture) {
|
if (texture != data->drawstate.texture) {
|
||||||
const GLenum textype = data->textype;
|
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
if (texturedata->yuv) {
|
if (texturedata->yuv) {
|
||||||
if (data->GL_ARB_multitexture_supported) {
|
data->glActiveTextureARB(GL_TEXTURE2_ARB);
|
||||||
data->glActiveTextureARB(GL_TEXTURE2_ARB);
|
|
||||||
}
|
|
||||||
data->glBindTexture(textype, texturedata->vtexture);
|
data->glBindTexture(textype, texturedata->vtexture);
|
||||||
|
|
||||||
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->GL_ARB_multitexture_supported) {
|
|
||||||
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
|
||||||
}
|
|
||||||
data->glBindTexture(textype, texturedata->utexture);
|
data->glBindTexture(textype, texturedata->utexture);
|
||||||
|
|
||||||
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (texturedata->nv12) {
|
if (texturedata->nv12) {
|
||||||
if (data->GL_ARB_multitexture_supported) {
|
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||||
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
|
||||||
}
|
|
||||||
data->glBindTexture(textype, texturedata->utexture);
|
data->glBindTexture(textype, texturedata->utexture);
|
||||||
|
|
||||||
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (data->GL_ARB_multitexture_supported) {
|
if (data->GL_ARB_multitexture_supported) {
|
||||||
@@ -1182,11 +1135,67 @@ static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
|
|||||||
}
|
}
|
||||||
data->glBindTexture(textype, texturedata->texture);
|
data->glBindTexture(textype, texturedata->texture);
|
||||||
|
|
||||||
|
data->drawstate.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->data.draw.texture_scale_mode != texturedata->texture_scale_mode) {
|
||||||
|
#ifdef SDL_HAVE_YUV
|
||||||
|
if (texturedata->yuv) {
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE2);
|
||||||
|
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE1);
|
||||||
|
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE0);
|
||||||
|
} else if (texturedata->nv12) {
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE1);
|
||||||
|
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
texturedata->texture_scale_mode = cmd->data.draw.texture_scale_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->data.draw.texture_address_mode != texturedata->texture_address_mode) {
|
||||||
|
#ifdef SDL_HAVE_YUV
|
||||||
|
if (texturedata->yuv) {
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE2);
|
||||||
|
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE1);
|
||||||
|
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||||
|
} else if (texturedata->nv12) {
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE1);
|
||||||
|
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTextureARB(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->drawstate.texture = texture;
|
texturedata->texture_address_mode = cmd->data.draw.texture_address_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1372,6 +1381,8 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
|
|||||||
same texture, we can combine them all into a single draw call. */
|
same texture, we can combine them all into a single draw call. */
|
||||||
SDL_Texture *thistexture = cmd->data.draw.texture;
|
SDL_Texture *thistexture = cmd->data.draw.texture;
|
||||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||||
|
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
|
||||||
|
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode;
|
||||||
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
||||||
SDL_RenderCommand *finalcmd = cmd;
|
SDL_RenderCommand *finalcmd = cmd;
|
||||||
SDL_RenderCommand *nextcmd = cmd->next;
|
SDL_RenderCommand *nextcmd = cmd->next;
|
||||||
@@ -1381,7 +1392,10 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
|
|||||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||||
if (nextcmdtype != thiscmdtype) {
|
if (nextcmdtype != thiscmdtype) {
|
||||||
break; // can't go any further on this draw call, different render command up next.
|
break; // can't go any further on this draw call, different render command up next.
|
||||||
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
|
} else if (nextcmd->data.draw.texture != thistexture ||
|
||||||
|
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
|
||||||
|
nextcmd->data.draw.texture_address_mode != thisaddressmode ||
|
||||||
|
nextcmd->data.draw.blend != thisblend) {
|
||||||
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
||||||
} else {
|
} else {
|
||||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||||
@@ -1656,7 +1670,6 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = GL_LockTexture;
|
renderer->LockTexture = GL_LockTexture;
|
||||||
renderer->UnlockTexture = GL_UnlockTexture;
|
renderer->UnlockTexture = GL_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = GL_SetRenderTarget;
|
renderer->SetRenderTarget = GL_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = GL_QueueNoOp;
|
renderer->QueueSetViewport = GL_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = GL_QueueNoOp;
|
renderer->QueueSetDrawColor = GL_QueueNoOp;
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ typedef struct GLES2_TextureData
|
|||||||
GLuint texture_u;
|
GLuint texture_u;
|
||||||
GLuint texture_u_external;
|
GLuint texture_u_external;
|
||||||
#endif
|
#endif
|
||||||
|
SDL_ScaleMode texture_scale_mode;
|
||||||
|
SDL_TextureAddressMode texture_address_mode;
|
||||||
GLES2_FBOList *fbo;
|
GLES2_FBOList *fbo;
|
||||||
} GLES2_TextureData;
|
} GLES2_TextureData;
|
||||||
|
|
||||||
@@ -168,6 +170,7 @@ typedef struct GLES2_RenderData
|
|||||||
|
|
||||||
bool debug_enabled;
|
bool debug_enabled;
|
||||||
|
|
||||||
|
bool GL_OES_EGL_image_external_supported;
|
||||||
bool GL_EXT_blend_minmax_supported;
|
bool GL_EXT_blend_minmax_supported;
|
||||||
|
|
||||||
#define SDL_PROC(ret, func, params) ret (APIENTRY *func) params;
|
#define SDL_PROC(ret, func, params) ret (APIENTRY *func) params;
|
||||||
@@ -987,8 +990,8 @@ static bool SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (texture) {
|
if (texture) {
|
||||||
SDL_Vertex *verts = (SDL_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first);
|
uintptr_t base = (uintptr_t)vertices + cmd->data.draw.first; // address of first vertex, or base offset when using VBOs.
|
||||||
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->tex_coord);
|
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)(base + offsetof(SDL_Vertex, tex_coord)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GLES2_SelectProgram(data, imgsrc, texture ? texture->colorspace : SDL_COLORSPACE_SRGB)) {
|
if (!GLES2_SelectProgram(data, imgsrc, texture ? texture->colorspace : SDL_COLORSPACE_SRGB)) {
|
||||||
@@ -1021,14 +1024,31 @@ static bool SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, c
|
|||||||
|
|
||||||
// all drawing commands use this
|
// all drawing commands use this
|
||||||
{
|
{
|
||||||
SDL_VertexSolid *verts = (SDL_VertexSolid *)(((Uint8 *)vertices) + cmd->data.draw.first);
|
uintptr_t base = (uintptr_t)vertices + cmd->data.draw.first; // address of first vertex, or base offset when using VBOs.
|
||||||
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->position);
|
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)(base + offsetof(SDL_VertexSolid, position)));
|
||||||
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_TRUE /* Normalized */, stride, (const GLvoid *)&verts->color);
|
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_TRUE /* Normalized */, stride, (const GLvoid *)(base + offsetof(SDL_VertexSolid, color)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool SetTextureScaleMode(GLES2_RenderData *data, GLenum textype, SDL_ScaleMode scaleMode)
|
||||||
|
{
|
||||||
|
switch (scaleMode) {
|
||||||
|
case SDL_SCALEMODE_NEAREST:
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
break;
|
||||||
|
case SDL_SCALEMODE_LINEAR:
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SDL_SetError("Unknown texture scale mode: %d", scaleMode);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
|
static bool SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
|
||||||
{
|
{
|
||||||
switch (addressMode) {
|
switch (addressMode) {
|
||||||
@@ -1051,6 +1071,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
|
|||||||
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
|
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
|
||||||
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
SDL_Texture *texture = cmd->data.draw.texture;
|
SDL_Texture *texture = cmd->data.draw.texture;
|
||||||
|
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
// Pick an appropriate shader
|
// Pick an appropriate shader
|
||||||
@@ -1172,19 +1193,66 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
|
|||||||
ret = SetDrawState(data, cmd, sourceType, vertices);
|
ret = SetDrawState(data, cmd, sourceType, vertices);
|
||||||
|
|
||||||
if (texture != data->drawstate.texture) {
|
if (texture != data->drawstate.texture) {
|
||||||
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
|
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
if (tdata->yuv) {
|
if (tdata->yuv) {
|
||||||
data->glActiveTexture(GL_TEXTURE2);
|
data->glActiveTexture(GL_TEXTURE2);
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||||
|
|
||||||
|
data->glActiveTexture(GL_TEXTURE1);
|
||||||
|
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||||
|
|
||||||
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
|
} else if (tdata->nv12) {
|
||||||
|
data->glActiveTexture(GL_TEXTURE1);
|
||||||
|
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||||
|
|
||||||
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||||
|
|
||||||
|
data->drawstate.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->data.draw.texture_scale_mode != tdata->texture_scale_mode) {
|
||||||
|
#ifdef SDL_HAVE_YUV
|
||||||
|
if (tdata->yuv) {
|
||||||
|
data->glActiveTexture(GL_TEXTURE2);
|
||||||
|
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTexture(GL_TEXTURE1);
|
||||||
|
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
|
} else if (tdata->nv12) {
|
||||||
|
data->glActiveTexture(GL_TEXTURE1);
|
||||||
|
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tdata->texture_scale_mode = cmd->data.draw.texture_scale_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->data.draw.texture_address_mode != tdata->texture_address_mode) {
|
||||||
|
#ifdef SDL_HAVE_YUV
|
||||||
|
if (tdata->yuv) {
|
||||||
|
data->glActiveTexture(GL_TEXTURE2);
|
||||||
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->glActiveTexture(GL_TEXTURE1);
|
data->glActiveTexture(GL_TEXTURE1);
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
|
||||||
|
|
||||||
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1192,8 +1260,6 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
|
|||||||
data->glActiveTexture(GL_TEXTURE0);
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
} else if (tdata->nv12) {
|
} else if (tdata->nv12) {
|
||||||
data->glActiveTexture(GL_TEXTURE1);
|
data->glActiveTexture(GL_TEXTURE1);
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
|
||||||
|
|
||||||
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1201,13 +1267,11 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
|
|||||||
data->glActiveTexture(GL_TEXTURE0);
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
|
||||||
|
|
||||||
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->drawstate.texture = texture;
|
tdata->texture_address_mode = cmd->data.draw.texture_address_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1269,7 +1333,8 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
|||||||
if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
|
if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
|
||||||
data->current_vertex_buffer = 0;
|
data->current_vertex_buffer = 0;
|
||||||
}
|
}
|
||||||
vertices = NULL; // attrib pointers will be offsets into the VBO.
|
// attrib pointers will be offsets into the VBO.
|
||||||
|
vertices = (void *)(uintptr_t)0; // must be the exact value 0, not NULL (the representation of NULL is not guaranteed to be 0).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (cmd) {
|
while (cmd) {
|
||||||
@@ -1384,6 +1449,8 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
|||||||
same texture, we can combine them all into a single draw call. */
|
same texture, we can combine them all into a single draw call. */
|
||||||
SDL_Texture *thistexture = cmd->data.draw.texture;
|
SDL_Texture *thistexture = cmd->data.draw.texture;
|
||||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||||
|
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
|
||||||
|
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode;
|
||||||
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
||||||
SDL_RenderCommand *finalcmd = cmd;
|
SDL_RenderCommand *finalcmd = cmd;
|
||||||
SDL_RenderCommand *nextcmd = cmd->next;
|
SDL_RenderCommand *nextcmd = cmd->next;
|
||||||
@@ -1393,7 +1460,10 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
|||||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||||
if (nextcmdtype != thiscmdtype) {
|
if (nextcmdtype != thiscmdtype) {
|
||||||
break; // can't go any further on this draw call, different render command up next.
|
break; // can't go any further on this draw call, different render command up next.
|
||||||
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
|
} else if (nextcmd->data.draw.texture != thistexture ||
|
||||||
|
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
|
||||||
|
nextcmd->data.draw.texture_address_mode != thisaddressmode ||
|
||||||
|
nextcmd->data.draw.blend != thisblend) {
|
||||||
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
||||||
} else {
|
} else {
|
||||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||||
@@ -1486,7 +1556,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
GLES2_TextureData *data;
|
GLES2_TextureData *data;
|
||||||
GLenum format;
|
GLenum format;
|
||||||
GLenum type;
|
GLenum type;
|
||||||
GLenum scaleMode;
|
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
@@ -1512,9 +1581,12 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
#endif
|
#endif
|
||||||
#ifdef GL_TEXTURE_EXTERNAL_OES
|
#ifdef GL_TEXTURE_EXTERNAL_OES
|
||||||
case SDL_PIXELFORMAT_EXTERNAL_OES:
|
case SDL_PIXELFORMAT_EXTERNAL_OES:
|
||||||
format = GL_NONE;
|
if (renderdata->GL_OES_EGL_image_external_supported) {
|
||||||
type = GL_NONE;
|
format = GL_NONE;
|
||||||
break;
|
type = GL_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SDL_FALLTHROUGH;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return SDL_SetError("Texture format not supported");
|
return SDL_SetError("Texture format not supported");
|
||||||
@@ -1544,7 +1616,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
data->texture_u = 0;
|
data->texture_u = 0;
|
||||||
data->texture_v = 0;
|
data->texture_v = 0;
|
||||||
#endif
|
#endif
|
||||||
scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
|
data->texture_scale_mode = SDL_SCALEMODE_INVALID;
|
||||||
|
data->texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID;
|
||||||
|
|
||||||
// Allocate a blob for image renderdata
|
// Allocate a blob for image renderdata
|
||||||
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
||||||
@@ -1583,8 +1656,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
}
|
}
|
||||||
renderdata->glActiveTexture(GL_TEXTURE2);
|
renderdata->glActiveTexture(GL_TEXTURE2);
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture_v);
|
renderdata->glBindTexture(data->texture_type, data->texture_v);
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
|
||||||
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
||||||
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v);
|
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v);
|
||||||
|
|
||||||
@@ -1599,8 +1670,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
}
|
}
|
||||||
renderdata->glActiveTexture(GL_TEXTURE1);
|
renderdata->glActiveTexture(GL_TEXTURE1);
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
|
||||||
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
||||||
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1622,8 +1691,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
}
|
}
|
||||||
renderdata->glActiveTexture(GL_TEXTURE1);
|
renderdata->glActiveTexture(GL_TEXTURE1);
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
|
||||||
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||||
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1648,8 +1715,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||||||
texture->internal = data;
|
texture->internal = data;
|
||||||
renderdata->glActiveTexture(GL_TEXTURE0);
|
renderdata->glActiveTexture(GL_TEXTURE0);
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture);
|
renderdata->glBindTexture(data->texture_type, data->texture);
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
|
||||||
if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
|
if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
|
||||||
renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
|
renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
|
||||||
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
||||||
@@ -1900,37 +1965,6 @@ static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
|
GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GLES2_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->internal;
|
|
||||||
GLES2_TextureData *data = (GLES2_TextureData *)texture->internal;
|
|
||||||
GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
|
|
||||||
|
|
||||||
#ifdef SDL_HAVE_YUV
|
|
||||||
if (data->yuv) {
|
|
||||||
renderdata->glActiveTexture(GL_TEXTURE2);
|
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture_v);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
|
|
||||||
renderdata->glActiveTexture(GL_TEXTURE1);
|
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
} else if (data->nv12) {
|
|
||||||
renderdata->glActiveTexture(GL_TEXTURE1);
|
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
renderdata->glActiveTexture(GL_TEXTURE0);
|
|
||||||
renderdata->glBindTexture(data->texture_type, data->texture);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
|
|
||||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool GLES2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool GLES2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
|
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
|
||||||
@@ -2151,7 +2185,6 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = GLES2_LockTexture;
|
renderer->LockTexture = GLES2_LockTexture;
|
||||||
renderer->UnlockTexture = GLES2_UnlockTexture;
|
renderer->UnlockTexture = GLES2_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = GLES2_SetRenderTarget;
|
renderer->SetRenderTarget = GLES2_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = GLES2_QueueNoOp;
|
renderer->QueueSetViewport = GLES2_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = GLES2_QueueNoOp;
|
renderer->QueueSetDrawColor = GLES2_QueueNoOp;
|
||||||
@@ -2172,7 +2205,11 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
|||||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
||||||
#endif
|
#endif
|
||||||
#ifdef GL_TEXTURE_EXTERNAL_OES
|
#ifdef GL_TEXTURE_EXTERNAL_OES
|
||||||
if (GLES2_CacheShader(data, GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES, GL_FRAGMENT_SHADER)) {
|
if (SDL_GL_ExtensionSupported("GL_OES_EGL_image_external")) {
|
||||||
|
data->GL_OES_EGL_image_external_supported = true;
|
||||||
|
if (!GLES2_CacheShader(data, GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES, GL_FRAGMENT_SHADER)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_EXTERNAL_OES);
|
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_EXTERNAL_OES);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -195,21 +195,6 @@ static bool PS2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PS2_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
GSTEXTURE *ps2_texture = (GSTEXTURE *)texture->internal;
|
|
||||||
/*
|
|
||||||
set texture filtering according to scaleMode
|
|
||||||
supported hint values are nearest (0, default) or linear (1)
|
|
||||||
gskit scale mode is either GS_FILTER_NEAREST (good for tile-map)
|
|
||||||
or GS_FILTER_LINEAR (good for scaling)
|
|
||||||
*/
|
|
||||||
uint32_t gsKitScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST
|
|
||||||
? GS_FILTER_NEAREST
|
|
||||||
: GS_FILTER_LINEAR);
|
|
||||||
ps2_texture->Filter = gsKitScaleMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool PS2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool PS2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -458,6 +443,16 @@ static bool PS2_RenderGeometry(SDL_Renderer *renderer, void *vertices, SDL_Rende
|
|||||||
const GSPRIMUVPOINT *verts = (GSPRIMUVPOINT *) (vertices + cmd->data.draw.first);
|
const GSPRIMUVPOINT *verts = (GSPRIMUVPOINT *) (vertices + cmd->data.draw.first);
|
||||||
GSTEXTURE *ps2_tex = (GSTEXTURE *)cmd->data.draw.texture->internal;
|
GSTEXTURE *ps2_tex = (GSTEXTURE *)cmd->data.draw.texture->internal;
|
||||||
|
|
||||||
|
switch (cmd->data.draw.texture_scale_mode) {
|
||||||
|
case SDL_SCALEMODE_NEAREST:
|
||||||
|
ps2_tex->Filter = GS_FILTER_NEAREST;
|
||||||
|
break;
|
||||||
|
case SDL_SCALEMODE_LINEAR:
|
||||||
|
ps2_tex->Filter = GS_FILTER_LINEAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
gsKit_TexManager_bind(data->gsGlobal, ps2_tex);
|
gsKit_TexManager_bind(data->gsGlobal, ps2_tex);
|
||||||
gsKit_prim_list_triangle_goraud_texture_uv_3d(data->gsGlobal, ps2_tex, count, verts);
|
gsKit_prim_list_triangle_goraud_texture_uv_3d(data->gsGlobal, ps2_tex, count, verts);
|
||||||
} else {
|
} else {
|
||||||
@@ -695,7 +690,6 @@ static bool PS2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
|||||||
renderer->UpdateTexture = PS2_UpdateTexture;
|
renderer->UpdateTexture = PS2_UpdateTexture;
|
||||||
renderer->LockTexture = PS2_LockTexture;
|
renderer->LockTexture = PS2_LockTexture;
|
||||||
renderer->UnlockTexture = PS2_UnlockTexture;
|
renderer->UnlockTexture = PS2_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = PS2_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = PS2_SetRenderTarget;
|
renderer->SetRenderTarget = PS2_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = PS2_QueueSetViewport;
|
renderer->QueueSetViewport = PS2_QueueSetViewport;
|
||||||
renderer->QueueSetDrawColor = PS2_QueueNoOp;
|
renderer->QueueSetDrawColor = PS2_QueueNoOp;
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ typedef struct
|
|||||||
unsigned int color;
|
unsigned int color;
|
||||||
int shadeModel;
|
int shadeModel;
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
|
SDL_ScaleMode texture_scale_mode;
|
||||||
|
SDL_TextureAddressMode texture_address_mode;
|
||||||
} PSP_BlendState;
|
} PSP_BlendState;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -538,20 +540,44 @@ static bool TextureShouldSwizzle(PSP_TextureData *psp_texture, SDL_Texture *text
|
|||||||
return !((texture->access == SDL_TEXTUREACCESS_TARGET) && InVram(psp_texture->data)) && texture->access != SDL_TEXTUREACCESS_STREAMING && (texture->w >= 16 || texture->h >= 16);
|
return !((texture->access == SDL_TEXTUREACCESS_TARGET) && InVram(psp_texture->data)) && texture->access != SDL_TEXTUREACCESS_STREAMING && (texture->w >= 16 || texture->h >= 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetTextureAddressMode(SDL_TextureAddressMode addressMode)
|
||||||
|
{
|
||||||
|
switch (addressMode) {
|
||||||
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
|
sceGuTexWrap(GU_CLAMP, GU_CLAMP);
|
||||||
|
break;
|
||||||
|
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||||
|
sceGuTexWrap(GU_REPEAT, GU_REPEAT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetTextureScaleMode(SDL_ScaleMode scaleMode)
|
||||||
|
{
|
||||||
|
switch (scaleMode) {
|
||||||
|
case SDL_SCALEMODE_NEAREST:
|
||||||
|
sceGuTexFilter(GU_NEAREST, GU_NEAREST);
|
||||||
|
break;
|
||||||
|
case SDL_SCALEMODE_LINEAR:
|
||||||
|
sceGuTexFilter(GU_LINEAR, GU_LINEAR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void TextureActivate(SDL_Texture *texture)
|
static void TextureActivate(SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
PSP_TextureData *psp_texture = (PSP_TextureData *)texture->internal;
|
PSP_TextureData *psp_texture = (PSP_TextureData *)texture->internal;
|
||||||
int scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GU_NEAREST : GU_LINEAR;
|
|
||||||
|
|
||||||
// Swizzling is useless with small textures.
|
// Swizzling is useless with small textures.
|
||||||
if (TextureShouldSwizzle(psp_texture, texture)) {
|
if (TextureShouldSwizzle(psp_texture, texture)) {
|
||||||
TextureSwizzle(psp_texture, NULL);
|
TextureSwizzle(psp_texture, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
sceGuTexWrap(GU_REPEAT, GU_REPEAT);
|
|
||||||
sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled);
|
sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled);
|
||||||
sceGuTexFilter(scaleMode, scaleMode); // GU_NEAREST good for tile-map
|
|
||||||
// GU_LINEAR good for scaling
|
|
||||||
sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data);
|
sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,11 +634,6 @@ static void PSP_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch);
|
PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PSP_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
// Nothing to do because TextureActivate takes care of it
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool PSP_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool PSP_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -1034,6 +1055,11 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->texture) {
|
||||||
|
SetTextureScaleMode(state->texture_scale_mode);
|
||||||
|
SetTextureAddressMode(state->texture_address_mode);
|
||||||
|
}
|
||||||
|
|
||||||
*current = *state;
|
*current = *state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,6 +1143,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
PSP_BlendState state = {
|
PSP_BlendState state = {
|
||||||
.color = drawstate.color,
|
.color = drawstate.color,
|
||||||
.texture = NULL,
|
.texture = NULL,
|
||||||
|
.texture_scale_mode = SDL_SCALEMODE_INVALID,
|
||||||
|
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID,
|
||||||
.mode = cmd->data.draw.blend,
|
.mode = cmd->data.draw.blend,
|
||||||
.shadeModel = GU_FLAT
|
.shadeModel = GU_FLAT
|
||||||
};
|
};
|
||||||
@@ -1132,6 +1160,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
PSP_BlendState state = {
|
PSP_BlendState state = {
|
||||||
.color = drawstate.color,
|
.color = drawstate.color,
|
||||||
.texture = NULL,
|
.texture = NULL,
|
||||||
|
.texture_scale_mode = SDL_SCALEMODE_INVALID,
|
||||||
|
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID,
|
||||||
.mode = cmd->data.draw.blend,
|
.mode = cmd->data.draw.blend,
|
||||||
.shadeModel = GU_FLAT
|
.shadeModel = GU_FLAT
|
||||||
};
|
};
|
||||||
@@ -1147,6 +1177,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
PSP_BlendState state = {
|
PSP_BlendState state = {
|
||||||
.color = drawstate.color,
|
.color = drawstate.color,
|
||||||
.texture = NULL,
|
.texture = NULL,
|
||||||
|
.texture_scale_mode = SDL_SCALEMODE_INVALID,
|
||||||
|
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID,
|
||||||
.mode = cmd->data.draw.blend,
|
.mode = cmd->data.draw.blend,
|
||||||
.shadeModel = GU_FLAT
|
.shadeModel = GU_FLAT
|
||||||
};
|
};
|
||||||
@@ -1162,6 +1194,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
PSP_BlendState state = {
|
PSP_BlendState state = {
|
||||||
.color = drawstate.color,
|
.color = drawstate.color,
|
||||||
.texture = cmd->data.draw.texture,
|
.texture = cmd->data.draw.texture,
|
||||||
|
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
|
||||||
|
.texture_address_mode = cmd->data.draw.texture_address_mode,
|
||||||
.mode = cmd->data.draw.blend,
|
.mode = cmd->data.draw.blend,
|
||||||
.shadeModel = GU_SMOOTH
|
.shadeModel = GU_SMOOTH
|
||||||
};
|
};
|
||||||
@@ -1176,6 +1210,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
PSP_BlendState state = {
|
PSP_BlendState state = {
|
||||||
.color = drawstate.color,
|
.color = drawstate.color,
|
||||||
.texture = cmd->data.draw.texture,
|
.texture = cmd->data.draw.texture,
|
||||||
|
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
|
||||||
|
.texture_address_mode = cmd->data.draw.texture_address_mode,
|
||||||
.mode = cmd->data.draw.blend,
|
.mode = cmd->data.draw.blend,
|
||||||
.shadeModel = GU_SMOOTH
|
.shadeModel = GU_SMOOTH
|
||||||
};
|
};
|
||||||
@@ -1197,11 +1233,12 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||||||
const VertTCV *verts = (VertTCV *)(gpumem + cmd->data.draw.first);
|
const VertTCV *verts = (VertTCV *)(gpumem + cmd->data.draw.first);
|
||||||
PSP_BlendState state = {
|
PSP_BlendState state = {
|
||||||
.color = drawstate.color,
|
.color = drawstate.color,
|
||||||
.texture = NULL,
|
.texture = cmd->data.draw.texture,
|
||||||
|
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
|
||||||
|
.texture_address_mode = cmd->data.draw.texture_address_mode,
|
||||||
.mode = cmd->data.draw.blend,
|
.mode = cmd->data.draw.blend,
|
||||||
.shadeModel = GU_FLAT
|
.shadeModel = GU_SMOOTH
|
||||||
};
|
};
|
||||||
TextureActivate(cmd->data.draw.texture);
|
|
||||||
PSP_SetBlendState(data, &state);
|
PSP_SetBlendState(data, &state);
|
||||||
sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
|
sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
|
||||||
}
|
}
|
||||||
@@ -1310,7 +1347,6 @@ static bool PSP_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
|||||||
renderer->UpdateTexture = PSP_UpdateTexture;
|
renderer->UpdateTexture = PSP_UpdateTexture;
|
||||||
renderer->LockTexture = PSP_LockTexture;
|
renderer->LockTexture = PSP_LockTexture;
|
||||||
renderer->UnlockTexture = PSP_UnlockTexture;
|
renderer->UnlockTexture = PSP_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = PSP_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = PSP_SetRenderTarget;
|
renderer->SetRenderTarget = PSP_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = PSP_QueueNoOp;
|
renderer->QueueSetViewport = PSP_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = PSP_QueueNoOp;
|
renderer->QueueSetDrawColor = PSP_QueueNoOp;
|
||||||
|
|||||||
@@ -171,10 +171,6 @@ static void SW_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SW_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
SW_RenderData *data = (SW_RenderData *)renderer->internal;
|
SW_RenderData *data = (SW_RenderData *)renderer->internal;
|
||||||
@@ -317,7 +313,7 @@ static bool Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *sur
|
|||||||
|
|
||||||
static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture,
|
static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture,
|
||||||
const SDL_Rect *srcrect, const SDL_Rect *final_rect,
|
const SDL_Rect *srcrect, const SDL_Rect *final_rect,
|
||||||
const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y)
|
const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y, const SDL_ScaleMode scaleMode)
|
||||||
{
|
{
|
||||||
SDL_Surface *src = (SDL_Surface *)texture->internal;
|
SDL_Surface *src = (SDL_Surface *)texture->internal;
|
||||||
SDL_Rect tmp_rect;
|
SDL_Rect tmp_rect;
|
||||||
@@ -412,7 +408,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
|
|||||||
result = false;
|
result = false;
|
||||||
} else {
|
} else {
|
||||||
SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE);
|
SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE);
|
||||||
result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode);
|
result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, scaleMode);
|
||||||
SDL_DestroySurface(src_clone);
|
SDL_DestroySurface(src_clone);
|
||||||
src_clone = src_scaled;
|
src_clone = src_scaled;
|
||||||
src_scaled = NULL;
|
src_scaled = NULL;
|
||||||
@@ -429,7 +425,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
|
|||||||
SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, center,
|
SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, center,
|
||||||
&rect_dest, &cangle, &sangle);
|
&rect_dest, &cangle, &sangle);
|
||||||
src_rotated = SDLgfx_rotateSurface(src_clone, angle,
|
src_rotated = SDLgfx_rotateSurface(src_clone, angle,
|
||||||
(texture->scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
|
(scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
|
||||||
&rect_dest, cangle, sangle, center);
|
&rect_dest, cangle, sangle, center);
|
||||||
if (!src_rotated) {
|
if (!src_rotated) {
|
||||||
result = false;
|
result = false;
|
||||||
@@ -460,7 +456,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
|
|||||||
SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
|
SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
|
||||||
}
|
}
|
||||||
// Renderer scaling, if needed
|
// Renderer scaling, if needed
|
||||||
result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
|
result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode);
|
||||||
} else {
|
} else {
|
||||||
/* The NONE blend mode requires three steps to get the pixels onto the destination surface.
|
/* The NONE blend mode requires three steps to get the pixels onto the destination surface.
|
||||||
* First, the area where the rotated pixels will be blitted to get set to zero.
|
* First, the area where the rotated pixels will be blitted to get set to zero.
|
||||||
@@ -470,7 +466,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
|
|||||||
SDL_Rect mask_rect = tmp_rect;
|
SDL_Rect mask_rect = tmp_rect;
|
||||||
SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE);
|
SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE);
|
||||||
// Renderer scaling, if needed
|
// Renderer scaling, if needed
|
||||||
result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
|
result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode);
|
||||||
if (result) {
|
if (result) {
|
||||||
/* The next step copies the alpha value. This is done with the BLEND blend mode and
|
/* The next step copies the alpha value. This is done with the BLEND blend mode and
|
||||||
* by modulating the source colors with 0. Since the destination is all zeros, this
|
* by modulating the source colors with 0. Since the destination is all zeros, this
|
||||||
@@ -479,7 +475,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
|
|||||||
SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
|
SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
|
||||||
mask_rect = tmp_rect;
|
mask_rect = tmp_rect;
|
||||||
// Renderer scaling, if needed
|
// Renderer scaling, if needed
|
||||||
result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
|
result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode);
|
||||||
if (result) {
|
if (result) {
|
||||||
/* The last step gets the color values in place. The ADD blend mode simply adds them to
|
/* The last step gets the color values in place. The ADD blend mode simply adds them to
|
||||||
* the destination (where the color values are all zero). However, because the ADD blend
|
* the destination (where the color values are all zero). However, because the ADD blend
|
||||||
@@ -492,7 +488,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
|
|||||||
} else {
|
} else {
|
||||||
SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
|
SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
|
||||||
// Renderer scaling, if needed
|
// Renderer scaling, if needed
|
||||||
result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
|
result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode);
|
||||||
SDL_DestroySurface(src_rotated_rgb);
|
SDL_DestroySurface(src_rotated_rgb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -858,7 +854,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
|
|||||||
SDL_SetSurfaceColorMod(src, 255, 255, 255);
|
SDL_SetSurfaceColorMod(src, 255, 255, 255);
|
||||||
SDL_SetSurfaceAlphaMod(src, 255);
|
SDL_SetSurfaceAlphaMod(src, 255);
|
||||||
|
|
||||||
SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode);
|
SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, cmd->data.draw.texture_scale_mode);
|
||||||
|
|
||||||
SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod);
|
SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod);
|
||||||
SDL_SetSurfaceAlphaMod(tmp, alphaMod);
|
SDL_SetSurfaceAlphaMod(tmp, alphaMod);
|
||||||
@@ -869,7 +865,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
|
|||||||
// No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy()
|
// No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode);
|
SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, cmd->data.draw.texture_scale_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -889,7 +885,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
|
|||||||
|
|
||||||
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, ©data->srcrect,
|
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, ©data->srcrect,
|
||||||
©data->dstrect, copydata->angle, ©data->center, copydata->flip,
|
©data->dstrect, copydata->angle, ©data->center, copydata->flip,
|
||||||
copydata->scale_x, copydata->scale_y);
|
copydata->scale_x, copydata->scale_y, cmd->data.draw.texture_scale_mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1135,7 +1131,6 @@ bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, S
|
|||||||
renderer->UpdateTexture = SW_UpdateTexture;
|
renderer->UpdateTexture = SW_UpdateTexture;
|
||||||
renderer->LockTexture = SW_LockTexture;
|
renderer->LockTexture = SW_LockTexture;
|
||||||
renderer->UnlockTexture = SW_UnlockTexture;
|
renderer->UnlockTexture = SW_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = SW_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = SW_SetRenderTarget;
|
renderer->SetRenderTarget = SW_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = SW_QueueNoOp;
|
renderer->QueueSetViewport = SW_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = SW_QueueNoOp;
|
renderer->QueueSetDrawColor = SW_QueueNoOp;
|
||||||
|
|||||||
@@ -70,8 +70,6 @@ static bool VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
|||||||
static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer,
|
static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer,
|
||||||
SDL_Texture *texture);
|
SDL_Texture *texture);
|
||||||
|
|
||||||
static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode);
|
|
||||||
|
|
||||||
static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer,
|
static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer,
|
||||||
SDL_Texture *texture);
|
SDL_Texture *texture);
|
||||||
|
|
||||||
@@ -216,7 +214,6 @@ static bool VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window,
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = VITA_GXM_LockTexture;
|
renderer->LockTexture = VITA_GXM_LockTexture;
|
||||||
renderer->UnlockTexture = VITA_GXM_UnlockTexture;
|
renderer->UnlockTexture = VITA_GXM_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = VITA_GXM_SetRenderTarget;
|
renderer->SetRenderTarget = VITA_GXM_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = VITA_GXM_QueueNoOp;
|
renderer->QueueSetViewport = VITA_GXM_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor;
|
renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor;
|
||||||
@@ -295,9 +292,10 @@ static bool VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
|||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->internal = vita_texture;
|
vita_texture->scale_mode = SDL_SCALEMODE_INVALID;
|
||||||
|
vita_texture->address_mode = SDL_TEXTURE_ADDRESS_INVALID;
|
||||||
|
|
||||||
VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode);
|
texture->internal = vita_texture;
|
||||||
|
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
|
vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
|
||||||
@@ -582,25 +580,6 @@ static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
// This really improves framerate when using lock/unlock.
|
// This really improves framerate when using lock/unlock.
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal;
|
|
||||||
|
|
||||||
/*
|
|
||||||
set texture filtering according to scaleMode
|
|
||||||
supported hint values are nearest (0, default) or linear (1)
|
|
||||||
vitaScaleMode is either SCE_GXM_TEXTURE_FILTER_POINT (good for tile-map)
|
|
||||||
or SCE_GXM_TEXTURE_FILTER_LINEAR (good for scaling)
|
|
||||||
*/
|
|
||||||
|
|
||||||
int vitaScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST
|
|
||||||
? SCE_GXM_TEXTURE_FILTER_POINT
|
|
||||||
: SCE_GXM_TEXTURE_FILTER_LINEAR);
|
|
||||||
gxm_texture_set_filters(vita_texture->tex, vitaScaleMode, vitaScaleMode);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -909,9 +888,41 @@ static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (texture) {
|
||||||
|
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal;
|
||||||
|
|
||||||
|
if (cmd->data.draw.texture_scale_mode != vita_texture->scale_mode) {
|
||||||
|
switch (cmd->data.draw.texture_scale_mode) {
|
||||||
|
case SDL_SCALEMODE_NEAREST:
|
||||||
|
gxm_texture_set_filters(vita_texture->tex, SCE_GXM_TEXTURE_FILTER_POINT, SCE_GXM_TEXTURE_FILTER_POINT);
|
||||||
|
break;
|
||||||
|
case SDL_SCALEMODE_LINEAR:
|
||||||
|
gxm_texture_set_filters(vita_texture->tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vita_texture->scale_mode = cmd->data.draw.texture_scale_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->data.draw.texture_address_mode != vita_texture->address_mode) {
|
||||||
|
switch (cmd->data.draw.texture_address_mode) {
|
||||||
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
|
gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_CLAMP, SCE_GXM_TEXTURE_ADDR_CLAMP);
|
||||||
|
break;
|
||||||
|
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||||
|
gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_REPEAT, SCE_GXM_TEXTURE_ADDR_REPEAT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vita_texture->address_mode = cmd->data.draw.texture_address_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (texture != data->drawstate.texture) {
|
if (texture != data->drawstate.texture) {
|
||||||
if (texture) {
|
if (texture) {
|
||||||
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)cmd->data.draw.texture->internal;
|
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal;
|
||||||
sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex);
|
sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex);
|
||||||
}
|
}
|
||||||
data->drawstate.texture = texture;
|
data->drawstate.texture = texture;
|
||||||
|
|||||||
@@ -1122,6 +1122,12 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gxm_texture_set_address_mode(gxm_texture *texture, SceGxmTextureAddrMode u_mode, SceGxmTextureAddrMode v_mode)
|
||||||
|
{
|
||||||
|
sceGxmTextureSetUAddrMode(&texture->gxm_tex, u_mode);
|
||||||
|
sceGxmTextureSetVAddrMode(&texture->gxm_tex, v_mode);
|
||||||
|
}
|
||||||
|
|
||||||
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter)
|
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter)
|
||||||
{
|
{
|
||||||
sceGxmTextureSetMinFilter(&texture->gxm_tex, min_filter);
|
sceGxmTextureSetMinFilter(&texture->gxm_tex, min_filter);
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ void gxm_finish(SDL_Renderer *renderer);
|
|||||||
gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
|
gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
|
||||||
void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
|
void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
|
||||||
|
|
||||||
|
void gxm_texture_set_address_mode(gxm_texture *texture, SceGxmTextureAddrMode u_mode, SceGxmTextureAddrMode v_mode);
|
||||||
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
|
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
|
||||||
SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
|
SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
|
||||||
|
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ typedef struct
|
|||||||
float wscale;
|
float wscale;
|
||||||
bool yuv;
|
bool yuv;
|
||||||
bool nv12;
|
bool nv12;
|
||||||
|
SDL_ScaleMode scale_mode;
|
||||||
|
SDL_TextureAddressMode address_mode;
|
||||||
} VITA_GXM_TextureData;
|
} VITA_GXM_TextureData;
|
||||||
|
|
||||||
#endif // SDL_RENDER_VITA_GXM_TYPES_H
|
#endif // SDL_RENDER_VITA_GXM_TYPES_H
|
||||||
@@ -255,7 +255,6 @@ typedef struct
|
|||||||
VkRenderPass mainRenderpasses[VULKAN_RENDERPASS_COUNT];
|
VkRenderPass mainRenderpasses[VULKAN_RENDERPASS_COUNT];
|
||||||
VkFramebuffer mainFramebuffer;
|
VkFramebuffer mainFramebuffer;
|
||||||
VULKAN_Buffer stagingBuffer;
|
VULKAN_Buffer stagingBuffer;
|
||||||
VkFilter scaleMode;
|
|
||||||
SDL_Rect lockedRect;
|
SDL_Rect lockedRect;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
@@ -2600,7 +2599,6 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
|
|||||||
} else {
|
} else {
|
||||||
textureData->shader = SHADER_ADVANCED;
|
textureData->shader = SHADER_ADVANCED;
|
||||||
}
|
}
|
||||||
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
|
|
||||||
|
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
// YUV textures must have even width and height. Also create Ycbcr conversion
|
// YUV textures must have even width and height. Also create Ycbcr conversion
|
||||||
@@ -3093,17 +3091,6 @@ static void VULKAN_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
VULKAN_DestroyBuffer(rendererData, &textureData->stagingBuffer);
|
VULKAN_DestroyBuffer(rendererData, &textureData->stagingBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VULKAN_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
|
||||||
{
|
|
||||||
VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
|
|
||||||
|
|
||||||
if (!textureData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool VULKAN_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool VULKAN_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
|
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
|
||||||
@@ -3775,7 +3762,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
|
|||||||
|
|
||||||
VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
|
VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
|
||||||
|
|
||||||
switch (textureData->scaleMode) {
|
switch (cmd->data.draw.texture_scale_mode) {
|
||||||
case VK_FILTER_NEAREST:
|
case VK_FILTER_NEAREST:
|
||||||
switch (cmd->data.draw.texture_address_mode) {
|
switch (cmd->data.draw.texture_address_mode) {
|
||||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||||
@@ -3801,7 +3788,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
|
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
||||||
@@ -4290,7 +4277,6 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
|
|||||||
#endif
|
#endif
|
||||||
renderer->LockTexture = VULKAN_LockTexture;
|
renderer->LockTexture = VULKAN_LockTexture;
|
||||||
renderer->UnlockTexture = VULKAN_UnlockTexture;
|
renderer->UnlockTexture = VULKAN_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = VULKAN_SetTextureScaleMode;
|
|
||||||
renderer->SetRenderTarget = VULKAN_SetRenderTarget;
|
renderer->SetRenderTarget = VULKAN_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = VULKAN_QueueNoOp;
|
renderer->QueueSetViewport = VULKAN_QueueNoOp;
|
||||||
renderer->QueueSetDrawColor = VULKAN_QueueNoOp;
|
renderer->QueueSetDrawColor = VULKAN_QueueNoOp;
|
||||||
|
|||||||
@@ -533,6 +533,7 @@ void *SDL_aligned_alloc(size_t alignment, size_t size)
|
|||||||
{
|
{
|
||||||
size_t padding;
|
size_t padding;
|
||||||
Uint8 *result = NULL;
|
Uint8 *result = NULL;
|
||||||
|
size_t requested_size = size;
|
||||||
|
|
||||||
if (alignment < sizeof(void*)) {
|
if (alignment < sizeof(void*)) {
|
||||||
alignment = sizeof(void*);
|
alignment = sizeof(void*);
|
||||||
@@ -552,6 +553,11 @@ void *SDL_aligned_alloc(size_t alignment, size_t size)
|
|||||||
|
|
||||||
// Store the original pointer right before the returned value
|
// Store the original pointer right before the returned value
|
||||||
SDL_memcpy(result - sizeof(original), &original, sizeof(original));
|
SDL_memcpy(result - sizeof(original), &original, sizeof(original));
|
||||||
|
|
||||||
|
// Initialize the padding to zero
|
||||||
|
if (padding > 0) {
|
||||||
|
SDL_memset(result + requested_size, 0, padding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+10
-14
@@ -368,14 +368,12 @@ static size_t SDL_ScanUnsignedLongLongInternal(const char *text, int count, int
|
|||||||
negative = *text == '-';
|
negative = *text == '-';
|
||||||
++text;
|
++text;
|
||||||
}
|
}
|
||||||
if ((radix == 0 || radix == 16) && *text == '0' && text[1] != '\0') {
|
if ((radix == 0 || radix == 16) && *text == '0' && (text[1] == 'x' || text[1] == 'X')) {
|
||||||
|
text += 2;
|
||||||
|
radix = 16;
|
||||||
|
} else if (radix == 0 && *text == '0' && (text[1] >= '0' && text[1] <= '9')) {
|
||||||
++text;
|
++text;
|
||||||
if (*text == 'x' || *text == 'X') {
|
radix = 8;
|
||||||
radix = 16;
|
|
||||||
++text;
|
|
||||||
} else if (radix == 0) {
|
|
||||||
radix = 8;
|
|
||||||
}
|
|
||||||
} else if (radix == 0) {
|
} else if (radix == 0) {
|
||||||
radix = 10;
|
radix = 10;
|
||||||
}
|
}
|
||||||
@@ -462,14 +460,12 @@ static size_t SDL_ScanUnsignedLongLongInternalW(const wchar_t *text, int count,
|
|||||||
negative = *text == '-';
|
negative = *text == '-';
|
||||||
++text;
|
++text;
|
||||||
}
|
}
|
||||||
if ((radix == 0 || radix == 16) && *text == '0') {
|
if ((radix == 0 || radix == 16) && *text == '0' && (text[1] == 'x' || text[1] == 'X')) {
|
||||||
|
text += 2;
|
||||||
|
radix = 16;
|
||||||
|
} else if (radix == 0 && *text == '0' && (text[1] >= '0' && text[1] <= '9')) {
|
||||||
++text;
|
++text;
|
||||||
if (*text == 'x' || *text == 'X') {
|
radix = 8;
|
||||||
radix = 16;
|
|
||||||
++text;
|
|
||||||
} else if (radix == 0) {
|
|
||||||
radix = 8;
|
|
||||||
}
|
|
||||||
} else if (radix == 0) {
|
} else if (radix == 0) {
|
||||||
radix = 10;
|
radix = 10;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ static const char *video_usage[] = {
|
|||||||
"[--input-focus]",
|
"[--input-focus]",
|
||||||
"[--keyboard-grab]",
|
"[--keyboard-grab]",
|
||||||
"[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
|
"[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
|
||||||
"[--logical-scale-quality nearest|linear|best]",
|
|
||||||
"[--logical WxH]",
|
"[--logical WxH]",
|
||||||
"[--max-geometry WxH]",
|
"[--max-geometry WxH]",
|
||||||
"[--maximize]",
|
"[--maximize]",
|
||||||
|
|||||||
@@ -454,4 +454,5 @@ void SDLTest_LogAllocations(void)
|
|||||||
#undef ADD_LINE
|
#undef ADD_LINE
|
||||||
|
|
||||||
SDL_Log("%s", message);
|
SDL_Log("%s", message);
|
||||||
|
SDL_free_orig(message);
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem)
|
|||||||
|
|
||||||
void SDL_SignalSemaphore(SDL_Semaphore *sem)
|
void SDL_SignalSemaphore(SDL_Semaphore *sem)
|
||||||
{
|
{
|
||||||
if (sem) {
|
if (!sem) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#if !defined(HAVE_CLOCK_GETTIME) && defined(SDL_PLATFORM_APPLE)
|
#if !defined(HAVE_CLOCK_GETTIME) && defined(SDL_PLATFORM_APPLE)
|
||||||
#include <mach/clock.h>
|
#include <mach/clock.h>
|
||||||
@@ -186,7 +187,23 @@ bool SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime *dt, bool localTime)
|
|||||||
dt->second = tm->tm_sec;
|
dt->second = tm->tm_sec;
|
||||||
dt->nanosecond = ticks % SDL_NS_PER_SECOND;
|
dt->nanosecond = ticks % SDL_NS_PER_SECOND;
|
||||||
dt->day_of_week = tm->tm_wday;
|
dt->day_of_week = tm->tm_wday;
|
||||||
|
|
||||||
|
/* tm_gmtoff wasn't formally standardized until POSIX.1-2024, but practically it has been available on desktop
|
||||||
|
* *nix platforms such as Linux/glibc, FreeBSD, OpenBSD, NetBSD, OSX/macOS, and others since the 1990s.
|
||||||
|
*
|
||||||
|
* The notable exception is Solaris, where the timezone offset must still be retrieved in the strictly POSIX.1-2008
|
||||||
|
* compliant way.
|
||||||
|
*/
|
||||||
|
#if (_POSIX_VERSION >= 202405L) || (!defined(sun) && !defined(__sun))
|
||||||
dt->utc_offset = (int)tm->tm_gmtoff;
|
dt->utc_offset = (int)tm->tm_gmtoff;
|
||||||
|
#else
|
||||||
|
if (localTime) {
|
||||||
|
tzset();
|
||||||
|
dt->utc_offset = (int)timezone;
|
||||||
|
} else {
|
||||||
|
dt->utc_offset = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -544,7 +544,7 @@ void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
|||||||
mii.dwTypeData = label_w;
|
mii.dwTypeData = label_w;
|
||||||
mii.cch = (UINT) SDL_wcslen(label_w);
|
mii.cch = (UINT) SDL_wcslen(label_w);
|
||||||
|
|
||||||
if (!SetMenuItemInfoW(entry->parent->hMenu, (UINT) entry->id, TRUE, &mii)) {
|
if (!SetMenuItemInfoW(entry->parent->hMenu, (UINT) entry->id, FALSE, &mii)) {
|
||||||
SDL_SetError("Couldn't update tray entry label");
|
SDL_SetError("Couldn't update tray entry label");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user