mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 12:14:41 +02:00
update SDL3 to 3.2.10.
This commit is contained in:
+1
-1
@@ -227,7 +227,7 @@ set(MEGA_LIBVORBIS_VER "1.3.5")
|
|||||||
set(MEGA_LIBTHEORA_VER "1.1.1")
|
set(MEGA_LIBTHEORA_VER "1.1.1")
|
||||||
set(MEGA_FREETYPE_VER "2.13.2")
|
set(MEGA_FREETYPE_VER "2.13.2")
|
||||||
set(MEGA_SDL2_VER "2.28.5")
|
set(MEGA_SDL2_VER "2.28.5")
|
||||||
set(MEGA_SDL3_VER "3.1.1-preview")
|
set(MEGA_SDL3_VER "3.2.10")
|
||||||
set(MEGA_OPENAL_VER "1.23.1-bc7cb17")
|
set(MEGA_OPENAL_VER "1.23.1-bc7cb17")
|
||||||
set(MEGA_MODPLUG_VER "0.8.8.4")
|
set(MEGA_MODPLUG_VER "0.8.8.4")
|
||||||
|
|
||||||
|
|||||||
@@ -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.10")
|
||||||
|
|
||||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
set(SDL3_MAINPROJECT ON)
|
set(SDL3_MAINPROJECT ON)
|
||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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.10</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.10</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.10.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.10;
|
||||||
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.10.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.10;
|
||||||
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.10
|
||||||
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 = 10;
|
||||||
/*
|
/*
|
||||||
// Display InputType.SOURCE/CLASS of events and devices
|
// Display InputType.SOURCE/CLASS of events and devices
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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.10
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1096,9 +1195,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 +1219,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 +1243,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 +1268,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 +1290,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 +1315,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 +1344,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 +1380,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 +1413,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 +1446,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 +1477,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 +1503,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 +1528,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 +1550,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 10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This macro turns the version numbers into a numeric value.
|
* This macro turns the version numbers into a numeric value.
|
||||||
|
|||||||
+15
-1
@@ -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_
|
||||||
|
|||||||
@@ -1256,11 +1256,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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -1187,7 +1187,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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,10,0
|
||||||
PRODUCTVERSION 3,2,6,0
|
PRODUCTVERSION 3,2,10,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, 10, 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, 10, 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
|
||||||
@@ -642,6 +644,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 +1167,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
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -1893,9 +1893,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -998,6 +1022,12 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI
|
|||||||
SDL_SetMouseFocus(window);
|
SDL_SetMouseFocus(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate fractional wheel motion if integer mode is enabled
|
||||||
|
if (mouse->integer_mode_flags & 2) {
|
||||||
|
mouse->integer_mode_residual_scroll_x = SDL_modff(mouse->integer_mode_residual_scroll_x + x, &x);
|
||||||
|
mouse->integer_mode_residual_scroll_y = SDL_modff(mouse->integer_mode_residual_scroll_y + y, &y);
|
||||||
|
}
|
||||||
|
|
||||||
if (x == 0.0f && y == 0.0f) {
|
if (x == 0.0f && y == 0.0f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1138,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,13 @@ 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;
|
||||||
|
float integer_mode_residual_scroll_x;
|
||||||
|
float integer_mode_residual_scroll_y;
|
||||||
|
|
||||||
// Data common to all mice
|
// Data common to all mice
|
||||||
SDL_Window *focus;
|
SDL_Window *focus;
|
||||||
float x;
|
float x;
|
||||||
|
|||||||
@@ -2646,8 +2646,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(
|
||||||
|
|||||||
@@ -854,7 +854,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!");
|
||||||
|
|||||||
@@ -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,6 +1204,7 @@ 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 *windowLock;
|
SDL_Mutex *windowLock;
|
||||||
|
|
||||||
@@ -1577,6 +1579,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);
|
||||||
@@ -4634,7 +4640,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 +4790,7 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
|
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->vkCreateSemaphore(
|
vulkanResult = renderer->vkCreateSemaphore(
|
||||||
renderer->logicalDevice,
|
renderer->logicalDevice,
|
||||||
&semaphoreCreateInfo,
|
&semaphoreCreateInfo,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -4934,6 +4944,7 @@ 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->windowLock);
|
SDL_DestroyMutex(renderer->windowLock);
|
||||||
|
|
||||||
@@ -7081,12 +7092,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 +7112,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 +7128,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 +7198,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 +7267,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10429,7 +10444,6 @@ 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 presenting = false;
|
||||||
|
|
||||||
@@ -10545,12 +10559,10 @@ static bool VULKAN_Submit(
|
|||||||
renderer,
|
renderer,
|
||||||
renderer->submittedCommandBuffers[i],
|
renderer->submittedCommandBuffers[i],
|
||||||
false);
|
false);
|
||||||
|
|
||||||
commandBufferCleaned = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandBufferCleaned) {
|
if (renderer->checkEmptyAllocations) {
|
||||||
SDL_LockMutex(renderer->allocatorLock);
|
SDL_LockMutex(renderer->allocatorLock);
|
||||||
|
|
||||||
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
|
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
|
||||||
@@ -10566,6 +10578,8 @@ static bool VULKAN_Submit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderer->checkEmptyAllocations = false;
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11657,6 +11671,7 @@ 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->windowLock = SDL_CreateMutex();
|
renderer->windowLock = SDL_CreateMutex();
|
||||||
|
|
||||||
@@ -11718,7 +11733,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 timing
|
||||||
VULKAN_INTERNAL_RenderPassHashFunction,
|
VULKAN_INTERNAL_RenderPassHashFunction,
|
||||||
VULKAN_INTERNAL_RenderPassHashKeyMatch,
|
VULKAN_INTERNAL_RenderPassHashKeyMatch,
|
||||||
VULKAN_INTERNAL_RenderPassHashDestroy,
|
VULKAN_INTERNAL_RenderPassHashDestroy,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -641,6 +641,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,",
|
||||||
|
|||||||
@@ -427,6 +427,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 +1050,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 +1122,7 @@ 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;
|
||||||
|
joystick->is_virtual = (driver == &SDL_VIRTUAL_JoystickDriver);
|
||||||
|
|
||||||
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 +1177,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 +1255,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 +1275,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 +1295,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 +1315,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 +1335,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 +1355,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);
|
||||||
@@ -2305,6 +2341,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 +2408,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -160,6 +160,8 @@ struct joystick_hwdata
|
|||||||
WindowsGamingInputGamepadState *wgi_slot;
|
WindowsGamingInputGamepadState *wgi_slot;
|
||||||
#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;
|
||||||
@@ -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,11 +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
|
||||||
|
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
|
||||||
|
HRESULT hr;
|
||||||
|
gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
|
||||||
|
gamepad_state->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;
|
|
||||||
HRESULT hr;
|
|
||||||
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);
|
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;
|
||||||
@@ -1513,6 +1518,7 @@ static bool RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_
|
|||||||
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");
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -1962,8 +1962,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 +1969,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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
@@ -494,8 +489,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 +569,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 +779,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 +791,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 +1175,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;
|
||||||
|
|||||||
@@ -1070,10 +1070,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 {
|
||||||
@@ -1473,7 +1469,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
|
|||||||
if (texture != statecache->texture) {
|
if (texture != statecache->texture) {
|
||||||
id<MTLSamplerState> mtlsampler;
|
id<MTLSamplerState> mtlsampler;
|
||||||
|
|
||||||
if (texture->scaleMode == SDL_SCALEMODE_NEAREST) {
|
if (cmd->data.draw.texture_scale_mode == 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:
|
||||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP];
|
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP];
|
||||||
@@ -2129,7 +2125,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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#ifdef SDL_HAVE_BLIT_A
|
#ifdef SDL_HAVE_BLIT_A
|
||||||
|
|
||||||
|
#include "SDL_pixels_c.h"
|
||||||
#include "SDL_surface_c.h"
|
#include "SDL_surface_c.h"
|
||||||
|
|
||||||
// Functions to perform alpha blended blitting
|
// Functions to perform alpha blended blitting
|
||||||
@@ -968,6 +969,10 @@ static void Blit8888to8888PixelAlphaSwizzle(SDL_BlitInfo *info)
|
|||||||
int dstskip = info->dst_skip;
|
int dstskip = info->dst_skip;
|
||||||
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||||
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||||
|
bool fill_alpha = !dstfmt->Amask;
|
||||||
|
Uint32 dstAmask, dstAshift;
|
||||||
|
|
||||||
|
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
|
||||||
|
|
||||||
while (height--) {
|
while (height--) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -976,6 +981,9 @@ static void Blit8888to8888PixelAlphaSwizzle(SDL_BlitInfo *info)
|
|||||||
Uint32 src32 = *(Uint32 *)src;
|
Uint32 src32 = *(Uint32 *)src;
|
||||||
Uint32 dst32 = *(Uint32 *)dst;
|
Uint32 dst32 = *(Uint32 *)dst;
|
||||||
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
|
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
|
||||||
|
if (fill_alpha) {
|
||||||
|
dst32 |= dstAmask;
|
||||||
|
}
|
||||||
*(Uint32 *)dst = dst32;
|
*(Uint32 *)dst = dst32;
|
||||||
src += 4;
|
src += 4;
|
||||||
dst += 4;
|
dst += 4;
|
||||||
@@ -998,6 +1006,10 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
|
|||||||
int dstskip = info->dst_skip;
|
int dstskip = info->dst_skip;
|
||||||
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||||
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||||
|
bool fill_alpha = !dstfmt->Amask;
|
||||||
|
Uint32 dstAmask, dstAshift;
|
||||||
|
|
||||||
|
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
|
||||||
|
|
||||||
// The byte offsets for the start of each pixel
|
// The byte offsets for the start of each pixel
|
||||||
const __m128i mask_offsets = _mm_set_epi8(
|
const __m128i mask_offsets = _mm_set_epi8(
|
||||||
@@ -1011,7 +1023,7 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
|
|||||||
mask_offsets);
|
mask_offsets);
|
||||||
|
|
||||||
const __m128i alpha_splat_mask = _mm_add_epi8(_mm_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
|
const __m128i alpha_splat_mask = _mm_add_epi8(_mm_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
|
||||||
const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstfmt->Amask);
|
const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstAmask);
|
||||||
|
|
||||||
while (height--) {
|
while (height--) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -1057,7 +1069,11 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
|
|||||||
dst_hi = _mm_mulhi_epu16(dst_hi, _mm_set1_epi16(257));
|
dst_hi = _mm_mulhi_epu16(dst_hi, _mm_set1_epi16(257));
|
||||||
|
|
||||||
// Blend the pixels together and save the result
|
// Blend the pixels together and save the result
|
||||||
_mm_storeu_si128((__m128i *)dst, _mm_packus_epi16(dst_lo, dst_hi));
|
dst128 = _mm_packus_epi16(dst_lo, dst_hi);
|
||||||
|
if (fill_alpha) {
|
||||||
|
dst128 = _mm_or_si128(dst128, alpha_fill_mask);
|
||||||
|
}
|
||||||
|
_mm_storeu_si128((__m128i *)dst, dst128);
|
||||||
|
|
||||||
src += 16;
|
src += 16;
|
||||||
dst += 16;
|
dst += 16;
|
||||||
@@ -1067,6 +1083,9 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
|
|||||||
Uint32 src32 = *(Uint32 *)src;
|
Uint32 src32 = *(Uint32 *)src;
|
||||||
Uint32 dst32 = *(Uint32 *)dst;
|
Uint32 dst32 = *(Uint32 *)dst;
|
||||||
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
|
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
|
||||||
|
if (fill_alpha) {
|
||||||
|
dst32 |= dstAmask;
|
||||||
|
}
|
||||||
*(Uint32 *)dst = dst32;
|
*(Uint32 *)dst = dst32;
|
||||||
src += 4;
|
src += 4;
|
||||||
dst += 4;
|
dst += 4;
|
||||||
@@ -1091,6 +1110,10 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
|
|||||||
int dstskip = info->dst_skip;
|
int dstskip = info->dst_skip;
|
||||||
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||||
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||||
|
bool fill_alpha = !dstfmt->Amask;
|
||||||
|
Uint32 dstAmask, dstAshift;
|
||||||
|
|
||||||
|
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
|
||||||
|
|
||||||
// The byte offsets for the start of each pixel
|
// The byte offsets for the start of each pixel
|
||||||
const __m256i mask_offsets = _mm256_set_epi8(
|
const __m256i mask_offsets = _mm256_set_epi8(
|
||||||
@@ -1104,7 +1127,7 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
|
|||||||
mask_offsets);
|
mask_offsets);
|
||||||
|
|
||||||
const __m256i alpha_splat_mask = _mm256_add_epi8(_mm256_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
|
const __m256i alpha_splat_mask = _mm256_add_epi8(_mm256_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
|
||||||
const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstfmt->Amask);
|
const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstAmask);
|
||||||
|
|
||||||
while (height--) {
|
while (height--) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -1150,7 +1173,11 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
|
|||||||
dst_hi = _mm256_mulhi_epu16(dst_hi, _mm256_set1_epi16(257));
|
dst_hi = _mm256_mulhi_epu16(dst_hi, _mm256_set1_epi16(257));
|
||||||
|
|
||||||
// Blend the pixels together and save the result
|
// Blend the pixels together and save the result
|
||||||
_mm256_storeu_si256((__m256i *)dst, _mm256_packus_epi16(dst_lo, dst_hi));
|
dst256 = _mm256_packus_epi16(dst_lo, dst_hi);
|
||||||
|
if (fill_alpha) {
|
||||||
|
dst256 = _mm256_or_si256(dst256, alpha_fill_mask);
|
||||||
|
}
|
||||||
|
_mm256_storeu_si256((__m256i *)dst, dst256);
|
||||||
|
|
||||||
src += 32;
|
src += 32;
|
||||||
dst += 32;
|
dst += 32;
|
||||||
@@ -1160,6 +1187,9 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
|
|||||||
Uint32 src32 = *(Uint32 *)src;
|
Uint32 src32 = *(Uint32 *)src;
|
||||||
Uint32 dst32 = *(Uint32 *)dst;
|
Uint32 dst32 = *(Uint32 *)dst;
|
||||||
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
|
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
|
||||||
|
if (fill_alpha) {
|
||||||
|
dst32 |= dstAmask;
|
||||||
|
}
|
||||||
*(Uint32 *)dst = dst32;
|
*(Uint32 *)dst = dst32;
|
||||||
src += 4;
|
src += 4;
|
||||||
dst += 4;
|
dst += 4;
|
||||||
@@ -1184,6 +1214,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
|
|||||||
int dstskip = info->dst_skip;
|
int dstskip = info->dst_skip;
|
||||||
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||||
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||||
|
bool fill_alpha = !dstfmt->Amask;
|
||||||
|
Uint32 dstAmask, dstAshift;
|
||||||
|
|
||||||
|
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
|
||||||
|
|
||||||
// The byte offsets for the start of each pixel
|
// The byte offsets for the start of each pixel
|
||||||
const uint8x16_t mask_offsets = vreinterpretq_u8_u64(vcombine_u64(
|
const uint8x16_t mask_offsets = vreinterpretq_u8_u64(vcombine_u64(
|
||||||
@@ -1197,7 +1231,7 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
|
|||||||
((srcfmt->Bshift >> 3) << dstfmt->Bshift))));
|
((srcfmt->Bshift >> 3) << dstfmt->Bshift))));
|
||||||
|
|
||||||
const uint8x16_t alpha_splat_mask = vaddq_u8(vdupq_n_u8(srcfmt->Ashift >> 3), mask_offsets);
|
const uint8x16_t alpha_splat_mask = vaddq_u8(vdupq_n_u8(srcfmt->Ashift >> 3), mask_offsets);
|
||||||
const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstfmt->Amask));
|
const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstAmask));
|
||||||
|
|
||||||
while (height--) {
|
while (height--) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -1242,6 +1276,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
|
|||||||
// temp = vraddhn_u16(res_lo, vrshrq_n_u16(res_lo, 8));
|
// temp = vraddhn_u16(res_lo, vrshrq_n_u16(res_lo, 8));
|
||||||
// dst128 = vraddhn_high_u16(temp, res_hi, vrshrq_n_u16(res_hi, 8));
|
// dst128 = vraddhn_high_u16(temp, res_hi, vrshrq_n_u16(res_hi, 8));
|
||||||
|
|
||||||
|
if (fill_alpha) {
|
||||||
|
dst128 = vorrq_u8(dst128, alpha_fill_mask);
|
||||||
|
}
|
||||||
|
|
||||||
// Save the result
|
// Save the result
|
||||||
vst1q_u8(dst, dst128);
|
vst1q_u8(dst, dst128);
|
||||||
|
|
||||||
@@ -1266,6 +1304,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
|
|||||||
|
|
||||||
dst32 = vaddhn_u16(res, vshrq_n_u16(res, 8));
|
dst32 = vaddhn_u16(res, vshrq_n_u16(res, 8));
|
||||||
|
|
||||||
|
if (fill_alpha) {
|
||||||
|
dst32 = vorr_u8(dst32, vget_low_u8(alpha_fill_mask));
|
||||||
|
}
|
||||||
|
|
||||||
// Save the result, only low 32-bits
|
// Save the result, only low 32-bits
|
||||||
vst1_lane_u32((Uint32*)dst, vreinterpret_u32_u8(dst32), 0);
|
vst1_lane_u32((Uint32*)dst, vreinterpret_u32_u8(dst32), 0);
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#ifdef SDL_HAVE_BLIT_N
|
#ifdef SDL_HAVE_BLIT_N
|
||||||
|
|
||||||
|
#include "SDL_pixels_c.h"
|
||||||
#include "SDL_surface_c.h"
|
#include "SDL_surface_c.h"
|
||||||
#include "SDL_blit_copy.h"
|
#include "SDL_blit_copy.h"
|
||||||
|
|
||||||
@@ -2551,6 +2552,255 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert between two 8888 pixels with differing formats.
|
||||||
|
#define SWIZZLE_8888_SRC_ALPHA(src, dst, srcfmt, dstfmt) \
|
||||||
|
do { \
|
||||||
|
dst = (((src >> srcfmt->Rshift) & 0xFF) << dstfmt->Rshift) | \
|
||||||
|
(((src >> srcfmt->Gshift) & 0xFF) << dstfmt->Gshift) | \
|
||||||
|
(((src >> srcfmt->Bshift) & 0xFF) << dstfmt->Bshift) | \
|
||||||
|
(((src >> srcfmt->Ashift) & 0xFF) << dstfmt->Ashift); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SWIZZLE_8888_DST_ALPHA(src, dst, srcfmt, dstfmt, dstAmask) \
|
||||||
|
do { \
|
||||||
|
dst = (((src >> srcfmt->Rshift) & 0xFF) << dstfmt->Rshift) | \
|
||||||
|
(((src >> srcfmt->Gshift) & 0xFF) << dstfmt->Gshift) | \
|
||||||
|
(((src >> srcfmt->Bshift) & 0xFF) << dstfmt->Bshift) | \
|
||||||
|
dstAmask; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#ifdef SDL_SSE4_1_INTRINSICS
|
||||||
|
|
||||||
|
static void SDL_TARGETING("sse4.1") Blit8888to8888PixelSwizzleSSE41(SDL_BlitInfo *info)
|
||||||
|
{
|
||||||
|
int width = info->dst_w;
|
||||||
|
int height = info->dst_h;
|
||||||
|
Uint8 *src = info->src;
|
||||||
|
int srcskip = info->src_skip;
|
||||||
|
Uint8 *dst = info->dst;
|
||||||
|
int dstskip = info->dst_skip;
|
||||||
|
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||||
|
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||||
|
bool fill_alpha = (!srcfmt->Amask || !dstfmt->Amask);
|
||||||
|
Uint32 srcAmask, srcAshift;
|
||||||
|
Uint32 dstAmask, dstAshift;
|
||||||
|
|
||||||
|
SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
|
||||||
|
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
|
||||||
|
|
||||||
|
// The byte offsets for the start of each pixel
|
||||||
|
const __m128i mask_offsets = _mm_set_epi8(
|
||||||
|
12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
const __m128i convert_mask = _mm_add_epi32(
|
||||||
|
_mm_set1_epi32(
|
||||||
|
((srcfmt->Rshift >> 3) << dstfmt->Rshift) |
|
||||||
|
((srcfmt->Gshift >> 3) << dstfmt->Gshift) |
|
||||||
|
((srcfmt->Bshift >> 3) << dstfmt->Bshift) |
|
||||||
|
((srcAshift >> 3) << dstAshift)),
|
||||||
|
mask_offsets);
|
||||||
|
|
||||||
|
const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstAmask);
|
||||||
|
|
||||||
|
while (height--) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i + 4 <= width; i += 4) {
|
||||||
|
// Load 4 src pixels
|
||||||
|
__m128i src128 = _mm_loadu_si128((__m128i *)src);
|
||||||
|
|
||||||
|
// Convert to dst format
|
||||||
|
src128 = _mm_shuffle_epi8(src128, convert_mask);
|
||||||
|
|
||||||
|
if (fill_alpha) {
|
||||||
|
// Set the alpha channels of src to 255
|
||||||
|
src128 = _mm_or_si128(src128, alpha_fill_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the result
|
||||||
|
_mm_storeu_si128((__m128i *)dst, src128);
|
||||||
|
|
||||||
|
src += 16;
|
||||||
|
dst += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < width; ++i) {
|
||||||
|
Uint32 src32 = *(Uint32 *)src;
|
||||||
|
Uint32 dst32;
|
||||||
|
if (fill_alpha) {
|
||||||
|
SWIZZLE_8888_DST_ALPHA(src32, dst32, srcfmt, dstfmt, dstAmask);
|
||||||
|
} else {
|
||||||
|
SWIZZLE_8888_SRC_ALPHA(src32, dst32, srcfmt, dstfmt);
|
||||||
|
}
|
||||||
|
*(Uint32 *)dst = dst32;
|
||||||
|
src += 4;
|
||||||
|
dst += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
src += srcskip;
|
||||||
|
dst += dstskip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SDL_AVX2_INTRINSICS
|
||||||
|
|
||||||
|
static void SDL_TARGETING("avx2") Blit8888to8888PixelSwizzleAVX2(SDL_BlitInfo *info)
|
||||||
|
{
|
||||||
|
int width = info->dst_w;
|
||||||
|
int height = info->dst_h;
|
||||||
|
Uint8 *src = info->src;
|
||||||
|
int srcskip = info->src_skip;
|
||||||
|
Uint8 *dst = info->dst;
|
||||||
|
int dstskip = info->dst_skip;
|
||||||
|
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||||
|
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||||
|
bool fill_alpha = (!srcfmt->Amask || !dstfmt->Amask);
|
||||||
|
Uint32 srcAmask, srcAshift;
|
||||||
|
Uint32 dstAmask, dstAshift;
|
||||||
|
|
||||||
|
SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
|
||||||
|
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
|
||||||
|
|
||||||
|
// The byte offsets for the start of each pixel
|
||||||
|
const __m256i mask_offsets = _mm256_set_epi8(
|
||||||
|
28, 28, 28, 28, 24, 24, 24, 24, 20, 20, 20, 20, 16, 16, 16, 16, 12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
const __m256i convert_mask = _mm256_add_epi32(
|
||||||
|
_mm256_set1_epi32(
|
||||||
|
((srcfmt->Rshift >> 3) << dstfmt->Rshift) |
|
||||||
|
((srcfmt->Gshift >> 3) << dstfmt->Gshift) |
|
||||||
|
((srcfmt->Bshift >> 3) << dstfmt->Bshift) |
|
||||||
|
((srcAshift >> 3) << dstAshift)),
|
||||||
|
mask_offsets);
|
||||||
|
|
||||||
|
const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstAmask);
|
||||||
|
|
||||||
|
while (height--) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i + 8 <= width; i += 8) {
|
||||||
|
// Load 8 src pixels
|
||||||
|
__m256i src256 = _mm256_loadu_si256((__m256i *)src);
|
||||||
|
|
||||||
|
// Convert to dst format
|
||||||
|
src256 = _mm256_shuffle_epi8(src256, convert_mask);
|
||||||
|
|
||||||
|
if (fill_alpha) {
|
||||||
|
// Set the alpha channels of src to 255
|
||||||
|
src256 = _mm256_or_si256(src256, alpha_fill_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the result
|
||||||
|
_mm256_storeu_si256((__m256i *)dst, src256);
|
||||||
|
|
||||||
|
src += 32;
|
||||||
|
dst += 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < width; ++i) {
|
||||||
|
Uint32 src32 = *(Uint32 *)src;
|
||||||
|
Uint32 dst32;
|
||||||
|
if (fill_alpha) {
|
||||||
|
SWIZZLE_8888_DST_ALPHA(src32, dst32, srcfmt, dstfmt, dstAmask);
|
||||||
|
} else {
|
||||||
|
SWIZZLE_8888_SRC_ALPHA(src32, dst32, srcfmt, dstfmt);
|
||||||
|
}
|
||||||
|
*(Uint32 *)dst = dst32;
|
||||||
|
src += 4;
|
||||||
|
dst += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
src += srcskip;
|
||||||
|
dst += dstskip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SDL_NEON_INTRINSICS) && (__ARM_ARCH >= 8)
|
||||||
|
|
||||||
|
static void Blit8888to8888PixelSwizzleNEON(SDL_BlitInfo *info)
|
||||||
|
{
|
||||||
|
int width = info->dst_w;
|
||||||
|
int height = info->dst_h;
|
||||||
|
Uint8 *src = info->src;
|
||||||
|
int srcskip = info->src_skip;
|
||||||
|
Uint8 *dst = info->dst;
|
||||||
|
int dstskip = info->dst_skip;
|
||||||
|
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||||
|
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||||
|
bool fill_alpha = (!srcfmt->Amask || !dstfmt->Amask);
|
||||||
|
Uint32 srcAmask, srcAshift;
|
||||||
|
Uint32 dstAmask, dstAshift;
|
||||||
|
|
||||||
|
SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
|
||||||
|
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
|
||||||
|
|
||||||
|
// The byte offsets for the start of each pixel
|
||||||
|
const uint8x16_t mask_offsets = vreinterpretq_u8_u64(vcombine_u64(
|
||||||
|
vcreate_u64(0x0404040400000000), vcreate_u64(0x0c0c0c0c08080808)));
|
||||||
|
|
||||||
|
const uint8x16_t convert_mask = vreinterpretq_u8_u32(vaddq_u32(
|
||||||
|
vreinterpretq_u32_u8(mask_offsets),
|
||||||
|
vdupq_n_u32(
|
||||||
|
((srcfmt->Rshift >> 3) << dstfmt->Rshift) |
|
||||||
|
((srcfmt->Gshift >> 3) << dstfmt->Gshift) |
|
||||||
|
((srcfmt->Bshift >> 3) << dstfmt->Bshift) |
|
||||||
|
((srcAshift >> 3) << dstAshift))));
|
||||||
|
|
||||||
|
const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstAmask));
|
||||||
|
|
||||||
|
while (height--) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i + 4 <= width; i += 4) {
|
||||||
|
// Load 4 src pixels
|
||||||
|
uint8x16_t src128 = vld1q_u8(src);
|
||||||
|
|
||||||
|
// Convert to dst format
|
||||||
|
src128 = vqtbl1q_u8(src128, convert_mask);
|
||||||
|
|
||||||
|
if (fill_alpha) {
|
||||||
|
// Set the alpha channels of src to 255
|
||||||
|
src128 = vorrq_u8(src128, alpha_fill_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the result
|
||||||
|
vst1q_u8(dst, src128);
|
||||||
|
|
||||||
|
src += 16;
|
||||||
|
dst += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process 1 pixel per iteration, max 3 iterations, same calculations as above
|
||||||
|
for (; i < width; ++i) {
|
||||||
|
// Top 32-bits will be not used in src32
|
||||||
|
uint8x8_t src32 = vreinterpret_u8_u32(vld1_dup_u32((Uint32*)src));
|
||||||
|
|
||||||
|
// Convert to dst format
|
||||||
|
src32 = vtbl1_u8(src32, vget_low_u8(convert_mask));
|
||||||
|
|
||||||
|
if (fill_alpha) {
|
||||||
|
// Set the alpha channels of src to 255
|
||||||
|
src32 = vorr_u8(src32, vget_low_u8(alpha_fill_mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the result, only low 32-bits
|
||||||
|
vst1_lane_u32((Uint32*)dst, vreinterpret_u32_u8(src32), 0);
|
||||||
|
|
||||||
|
src += 4;
|
||||||
|
dst += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
src += srcskip;
|
||||||
|
dst += dstskip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// Blit_3or4_to_3or4__same_rgb: 3 or 4 bpp, same RGB triplet
|
// Blit_3or4_to_3or4__same_rgb: 3 or 4 bpp, same RGB triplet
|
||||||
static void Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo *info)
|
static void Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo *info)
|
||||||
{
|
{
|
||||||
@@ -2873,6 +3123,23 @@ SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface *surface)
|
|||||||
|
|
||||||
switch (surface->map.info.flags & ~SDL_COPY_RLE_MASK) {
|
switch (surface->map.info.flags & ~SDL_COPY_RLE_MASK) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (SDL_PIXELLAYOUT(srcfmt->format) == SDL_PACKEDLAYOUT_8888 &&
|
||||||
|
SDL_PIXELLAYOUT(dstfmt->format) == SDL_PACKEDLAYOUT_8888) {
|
||||||
|
#ifdef SDL_AVX2_INTRINSICS
|
||||||
|
if (SDL_HasAVX2()) {
|
||||||
|
return Blit8888to8888PixelSwizzleAVX2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef SDL_SSE4_1_INTRINSICS
|
||||||
|
if (SDL_HasSSE41()) {
|
||||||
|
return Blit8888to8888PixelSwizzleSSE41;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(SDL_NEON_INTRINSICS) && (__ARM_ARCH >= 8)
|
||||||
|
return Blit8888to8888PixelSwizzleNEON;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
blitfun = NULL;
|
blitfun = NULL;
|
||||||
if (dstfmt->bits_per_pixel > 8) {
|
if (dstfmt->bits_per_pixel > 8) {
|
||||||
Uint32 a_need = NO_ALPHA;
|
Uint32 a_need = NO_ALPHA;
|
||||||
|
|||||||
@@ -692,6 +692,34 @@ void SDL_QuitPixelFormatDetails(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift)
|
||||||
|
{
|
||||||
|
if (fmt->Amask) {
|
||||||
|
*mask = fmt->Amask;
|
||||||
|
*shift = fmt->Ashift;
|
||||||
|
} else {
|
||||||
|
*mask = ~(fmt->Rmask | fmt->Gmask | fmt->Bmask);
|
||||||
|
switch (*mask) {
|
||||||
|
case 0x000000FF:
|
||||||
|
*shift = 0;
|
||||||
|
break;
|
||||||
|
case 0x0000FF00:
|
||||||
|
*shift = 8;
|
||||||
|
break;
|
||||||
|
case 0x00FF0000:
|
||||||
|
*shift = 16;
|
||||||
|
break;
|
||||||
|
case 0xFF000000:
|
||||||
|
*shift = 24;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Should never happen
|
||||||
|
*shift = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format)
|
SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format)
|
||||||
{
|
{
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// Pixel format functions
|
// Pixel format functions
|
||||||
extern bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, size_t *size, size_t *pitch, bool minimalPitch);
|
extern void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift);
|
||||||
extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat pixel_format);
|
extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat pixel_format);
|
||||||
extern void SDL_QuitPixelFormatDetails(void);
|
extern void SDL_QuitPixelFormatDetails(void);
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, siz
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
||||||
|
if (format == SDL_PIXELFORMAT_MJPG) {
|
||||||
|
// We don't know in advance what it will be, we'll figure it out later.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SDL_CalculateYUVSize(format, width, height, &sz, &p)) {
|
if (!SDL_CalculateYUVSize(format, width, height, &sz, &p)) {
|
||||||
// Overflow...
|
// Overflow...
|
||||||
return false;
|
return false;
|
||||||
@@ -199,6 +204,11 @@ SDL_Surface *SDL_CreateSurface(int width, int height, SDL_PixelFormat format)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||||
|
SDL_InvalidParamError("format");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SDL_CalculateSurfaceSize(format, width, height, &size, &pitch, false /* not minimal pitch */)) {
|
if (!SDL_CalculateSurfaceSize(format, width, height, &size, &pitch, false /* not minimal pitch */)) {
|
||||||
// Overflow...
|
// Overflow...
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -214,7 +224,7 @@ SDL_Surface *SDL_CreateSurface(int width, int height, SDL_PixelFormat format)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface->w && surface->h) {
|
if (surface->w && surface->h && format != SDL_PIXELFORMAT_MJPG) {
|
||||||
surface->flags &= ~SDL_SURFACE_PREALLOCATED;
|
surface->flags &= ~SDL_SURFACE_PREALLOCATED;
|
||||||
surface->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), size);
|
surface->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), size);
|
||||||
if (!surface->pixels) {
|
if (!surface->pixels) {
|
||||||
@@ -245,6 +255,11 @@ SDL_Surface *SDL_CreateSurfaceFrom(int width, int height, SDL_PixelFormat format
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||||
|
SDL_InvalidParamError("format");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (pitch == 0 && !pixels) {
|
if (pitch == 0 && !pixels) {
|
||||||
// The application will fill these in later with valid values
|
// The application will fill these in later with valid values
|
||||||
} else {
|
} else {
|
||||||
@@ -1917,7 +1932,18 @@ SDL_Surface *SDL_ConvertSurfaceAndColorspace(SDL_Surface *surface, SDL_PixelForm
|
|||||||
SDL_SetSurfaceColorspace(convert, colorspace);
|
SDL_SetSurfaceColorspace(convert, colorspace);
|
||||||
|
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(format) || SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(format) || SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
|
||||||
if (!SDL_ConvertPixelsAndColorspace(surface->w, surface->h, surface->format, src_colorspace, src_properties, surface->pixels, surface->pitch, convert->format, colorspace, props, convert->pixels, convert->pitch)) {
|
if (surface->format == SDL_PIXELFORMAT_MJPG && format == SDL_PIXELFORMAT_MJPG) {
|
||||||
|
// Just do a straight pixel copy of the JPEG image
|
||||||
|
size_t size = (size_t)surface->pitch;
|
||||||
|
convert->pixels = SDL_malloc(size);
|
||||||
|
if (!convert->pixels) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
convert->flags &= ~SDL_SURFACE_PREALLOCATED;
|
||||||
|
convert->pitch = surface->pitch;
|
||||||
|
SDL_memcpy(convert->pixels, surface->pixels, size);
|
||||||
|
|
||||||
|
} else if (!SDL_ConvertPixelsAndColorspace(surface->w, surface->h, surface->format, src_colorspace, src_properties, surface->pixels, surface->pitch, convert->format, colorspace, props, convert->pixels, convert->pitch)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ struct SDL_Surface
|
|||||||
// Surface functions
|
// Surface functions
|
||||||
extern bool SDL_SurfaceValid(SDL_Surface *surface);
|
extern bool SDL_SurfaceValid(SDL_Surface *surface);
|
||||||
extern void SDL_UpdateSurfaceLockFlag(SDL_Surface *surface);
|
extern void SDL_UpdateSurfaceLockFlag(SDL_Surface *surface);
|
||||||
|
extern bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, size_t *size, size_t *pitch, bool minimalPitch);
|
||||||
extern float SDL_GetDefaultSDRWhitePoint(SDL_Colorspace colorspace);
|
extern float SDL_GetDefaultSDRWhitePoint(SDL_Colorspace colorspace);
|
||||||
extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace colorspace);
|
extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace colorspace);
|
||||||
extern float SDL_GetDefaultHDRHeadroom(SDL_Colorspace colorspace);
|
extern float SDL_GetDefaultHDRHeadroom(SDL_Colorspace colorspace);
|
||||||
|
|||||||
@@ -163,6 +163,8 @@ struct SDL_VideoDisplay
|
|||||||
float content_scale;
|
float content_scale;
|
||||||
SDL_HDROutputProperties HDR;
|
SDL_HDROutputProperties HDR;
|
||||||
|
|
||||||
|
// This is true if we are fullscreen or fullscreen is pending
|
||||||
|
bool fullscreen_active;
|
||||||
SDL_Window *fullscreen_window;
|
SDL_Window *fullscreen_window;
|
||||||
|
|
||||||
SDL_VideoDevice *device;
|
SDL_VideoDevice *device;
|
||||||
|
|||||||
@@ -1435,6 +1435,11 @@ void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode
|
|||||||
{
|
{
|
||||||
SDL_DisplayMode last_mode;
|
SDL_DisplayMode last_mode;
|
||||||
|
|
||||||
|
if (display->fullscreen_active) {
|
||||||
|
// This is a temporary mode change, don't save the desktop mode
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_copyp(&last_mode, &display->desktop_mode);
|
SDL_copyp(&last_mode, &display->desktop_mode);
|
||||||
|
|
||||||
if (display->desktop_mode.internal) {
|
if (display->desktop_mode.internal) {
|
||||||
@@ -1944,6 +1949,8 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
|
|||||||
SDL_MinimizeWindow(display->fullscreen_window);
|
SDL_MinimizeWindow(display->fullscreen_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
display->fullscreen_active = window->fullscreen_exclusive;
|
||||||
|
|
||||||
if (!SDL_SetDisplayModeForDisplay(display, mode)) {
|
if (!SDL_SetDisplayModeForDisplay(display, mode)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -1961,6 +1968,7 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
|
|||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0);
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0);
|
||||||
}
|
}
|
||||||
} else if (ret == SDL_FULLSCREEN_FAILED) {
|
} else if (ret == SDL_FULLSCREEN_FAILED) {
|
||||||
|
display->fullscreen_active = false;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1976,18 +1984,24 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
|
|||||||
* This is also unnecessary on Cocoa, Wayland, Win32, and X11 (will send SDL_EVENT_WINDOW_RESIZED).
|
* This is also unnecessary on Cocoa, Wayland, Win32, and X11 (will send SDL_EVENT_WINDOW_RESIZED).
|
||||||
*/
|
*/
|
||||||
if (!SDL_SendsFullscreenDimensions(_this)) {
|
if (!SDL_SendsFullscreenDimensions(_this)) {
|
||||||
|
SDL_Rect displayRect;
|
||||||
|
|
||||||
if (mode) {
|
if (mode) {
|
||||||
mode_w = mode->w;
|
mode_w = mode->w;
|
||||||
mode_h = mode->h;
|
mode_h = mode->h;
|
||||||
|
SDL_GetDisplayBounds(mode->displayID, &displayRect);
|
||||||
} else {
|
} else {
|
||||||
mode_w = display->desktop_mode.w;
|
mode_w = display->desktop_mode.w;
|
||||||
mode_h = display->desktop_mode.h;
|
mode_h = display->desktop_mode.h;
|
||||||
|
SDL_GetDisplayBounds(display->id, &displayRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->w != mode_w || window->h != mode_h) {
|
if (window->w != mode_w || window->h != mode_h) {
|
||||||
resized = true;
|
resized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, displayRect.x, displayRect.y);
|
||||||
|
|
||||||
if (resized) {
|
if (resized) {
|
||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, mode_w, mode_h);
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, mode_w, mode_h);
|
||||||
} else {
|
} else {
|
||||||
@@ -2005,6 +2019,8 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
|
|||||||
|
|
||||||
// Restore the desktop mode
|
// Restore the desktop mode
|
||||||
if (display) {
|
if (display) {
|
||||||
|
display->fullscreen_active = false;
|
||||||
|
|
||||||
SDL_SetDisplayModeForDisplay(display, NULL);
|
SDL_SetDisplayModeForDisplay(display, NULL);
|
||||||
}
|
}
|
||||||
if (commit) {
|
if (commit) {
|
||||||
@@ -2034,6 +2050,7 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_SendsFullscreenDimensions(_this)) {
|
if (!SDL_SendsFullscreenDimensions(_this)) {
|
||||||
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, window->windowed.x, window->windowed.y);
|
||||||
if (resized) {
|
if (resized) {
|
||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->windowed.w, window->windowed.h);
|
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->windowed.w, window->windowed.h);
|
||||||
} else {
|
} else {
|
||||||
@@ -2907,11 +2924,12 @@ bool SDL_GetWindowPosition(SDL_Window *window, int *x, int *y)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const bool use_pending = (window->flags & SDL_WINDOW_HIDDEN) && window->last_position_pending;
|
||||||
if (x) {
|
if (x) {
|
||||||
*x = window->x;
|
*x = use_pending ? window->pending.x : window->x;
|
||||||
}
|
}
|
||||||
if (y) {
|
if (y) {
|
||||||
*y = window->y;
|
*y = use_pending ? window->pending.y : window->y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -5387,6 +5405,10 @@ bool SDL_GetTextInputMultiline(SDL_PropertiesID props)
|
|||||||
static bool AutoShowingScreenKeyboard(void)
|
static bool AutoShowingScreenKeyboard(void)
|
||||||
{
|
{
|
||||||
const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD);
|
const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD);
|
||||||
|
if (!hint) {
|
||||||
|
// Steam will eventually have smarts about whether a keyboard is active, so always request the on-screen keyboard on Steam Deck
|
||||||
|
hint = SDL_GetHint("SteamDeck");
|
||||||
|
}
|
||||||
if (((!hint || SDL_strcasecmp(hint, "auto") == 0) && !SDL_HasKeyboard()) ||
|
if (((!hint || SDL_strcasecmp(hint, "auto") == 0) && !SDL_HasKeyboard()) ||
|
||||||
SDL_GetStringBoolean(hint, false)) {
|
SDL_GetStringBoolean(hint, false)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1628,26 +1628,44 @@ static bool SDL_ConvertPixels_SwapNV_std(int width, int height, const void *src,
|
|||||||
const int UVwidth = (width + 1) / 2;
|
const int UVwidth = (width + 1) / 2;
|
||||||
const int UVheight = (height + 1) / 2;
|
const int UVheight = (height + 1) / 2;
|
||||||
const int srcUVPitch = ((src_pitch + 1) / 2) * 2;
|
const int srcUVPitch = ((src_pitch + 1) / 2) * 2;
|
||||||
const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2) / sizeof(Uint16);
|
|
||||||
const int dstUVPitch = ((dst_pitch + 1) / 2) * 2;
|
const int dstUVPitch = ((dst_pitch + 1) / 2) * 2;
|
||||||
const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2) / sizeof(Uint16);
|
|
||||||
const Uint16 *srcUV;
|
|
||||||
Uint16 *dstUV;
|
|
||||||
|
|
||||||
// Skip the Y plane
|
// Skip the Y plane
|
||||||
src = (const Uint8 *)src + height * src_pitch;
|
src = (const Uint8 *)src + height * src_pitch;
|
||||||
dst = (Uint8 *)dst + height * dst_pitch;
|
dst = (Uint8 *)dst + height * dst_pitch;
|
||||||
|
|
||||||
srcUV = (const Uint16 *)src;
|
bool aligned = (((uintptr_t)src | (uintptr_t)dst) & 1) == 0;
|
||||||
dstUV = (Uint16 *)dst;
|
if (aligned) {
|
||||||
y = UVheight;
|
const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2) / sizeof(Uint16);
|
||||||
while (y--) {
|
const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2) / sizeof(Uint16);
|
||||||
x = UVwidth;
|
const Uint16 *srcUV = (const Uint16 *)src;
|
||||||
while (x--) {
|
Uint16 *dstUV = (Uint16 *)dst;
|
||||||
*dstUV++ = SDL_Swap16(*srcUV++);
|
y = UVheight;
|
||||||
|
while (y--) {
|
||||||
|
x = UVwidth;
|
||||||
|
while (x--) {
|
||||||
|
*dstUV++ = SDL_Swap16(*srcUV++);
|
||||||
|
}
|
||||||
|
srcUV += srcUVPitchLeft;
|
||||||
|
dstUV += dstUVPitchLeft;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2);
|
||||||
|
const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2);
|
||||||
|
const Uint8 *srcUV = (const Uint8 *)src;
|
||||||
|
Uint8 *dstUV = (Uint8 *)dst;
|
||||||
|
y = UVheight;
|
||||||
|
while (y--) {
|
||||||
|
x = UVwidth;
|
||||||
|
while (x--) {
|
||||||
|
Uint8 u = *srcUV++;
|
||||||
|
Uint8 v = *srcUV++;
|
||||||
|
*dstUV++ = v;
|
||||||
|
*dstUV++ = u;
|
||||||
|
}
|
||||||
|
srcUV += srcUVPitchLeft;
|
||||||
|
dstUV += dstUVPitchLeft;
|
||||||
}
|
}
|
||||||
srcUV += srcUVPitchLeft;
|
|
||||||
dstUV += dstUVPitchLeft;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -556,22 +556,24 @@ bool Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, S
|
|||||||
|
|
||||||
bool Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
bool Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
||||||
{
|
{
|
||||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->internal;
|
@autoreleasepool {
|
||||||
NSScreen *screen = GetNSScreenForDisplayID(displaydata->display);
|
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->internal;
|
||||||
|
NSScreen *screen = GetNSScreenForDisplayID(displaydata->display);
|
||||||
|
|
||||||
if (screen == nil) {
|
if (screen == nil) {
|
||||||
return SDL_SetError("Couldn't get NSScreen for display");
|
return SDL_SetError("Couldn't get NSScreen for display");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const NSRect frame = [screen visibleFrame];
|
||||||
|
rect->x = (int)frame.origin.x;
|
||||||
|
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
||||||
|
rect->w = (int)frame.size.width;
|
||||||
|
rect->h = (int)frame.size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
const NSRect frame = [screen visibleFrame];
|
|
||||||
rect->x = (int)frame.origin.x;
|
|
||||||
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
|
||||||
rect->w = (int)frame.size.width;
|
|
||||||
rect->h = (int)frame.size.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
|
bool Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
|
||||||
@@ -644,7 +646,9 @@ static CGError SetDisplayModeForDisplay(CGDirectDisplayID display, SDL_DisplayMo
|
|||||||
result = CGDisplaySetDisplayMode(display, moderef, NULL);
|
result = CGDisplaySetDisplayMode(display, moderef, NULL);
|
||||||
if (result == kCGErrorSuccess) {
|
if (result == kCGErrorSuccess) {
|
||||||
// If this mode works, try it first next time.
|
// If this mode works, try it first next time.
|
||||||
CFArrayExchangeValuesAtIndices(data->modes, i, 0);
|
if (i > 0) {
|
||||||
|
CFArrayExchangeValuesAtIndices(data->modes, i, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -868,14 +868,16 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
return NO; // we only allow you to make a Space on fullscreen desktop windows.
|
return NO; // we only allow you to make a Space on fullscreen desktop windows.
|
||||||
} else if (!state && window->last_fullscreen_exclusive_display) {
|
} else if (!state && window->last_fullscreen_exclusive_display) {
|
||||||
return NO; // we only handle leaving the Space on windows that were previously fullscreen desktop.
|
return NO; // we only handle leaving the Space on windows that were previously fullscreen desktop.
|
||||||
} else if (state == isFullscreenSpace) {
|
} else if (state == isFullscreenSpace && !inFullscreenTransition) {
|
||||||
return YES; // already there.
|
return YES; // already there.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inFullscreenTransition) {
|
if (inFullscreenTransition) {
|
||||||
if (state) {
|
if (state) {
|
||||||
|
[self clearPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
|
||||||
[self addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
|
[self addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
|
||||||
} else {
|
} else {
|
||||||
|
[self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
|
||||||
[self addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
|
[self addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
@@ -903,6 +905,11 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
pendingWindowOperation &= ~operation;
|
pendingWindowOperation &= ~operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)clearAllPendingWindowOperations
|
||||||
|
{
|
||||||
|
pendingWindowOperation = PENDING_OPERATION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)addPendingWindowOperation:(PendingWindowOperation)operation
|
- (void)addPendingWindowOperation:(PendingWindowOperation)operation
|
||||||
{
|
{
|
||||||
pendingWindowOperation |= operation;
|
pendingWindowOperation |= operation;
|
||||||
@@ -915,7 +922,8 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
|
|
||||||
- (BOOL)hasPendingWindowOperation
|
- (BOOL)hasPendingWindowOperation
|
||||||
{
|
{
|
||||||
return pendingWindowOperation != PENDING_OPERATION_NONE ||
|
// A pending zoom may be deferred until leaving fullscreen, so don't block on it.
|
||||||
|
return (pendingWindowOperation & ~PENDING_OPERATION_ZOOM) != PENDING_OPERATION_NONE ||
|
||||||
isMiniaturizing || inFullscreenTransition;
|
isMiniaturizing || inFullscreenTransition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1349,21 +1357,14 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
inFullscreenTransition = YES;
|
inFullscreenTransition = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is usually sent after an unexpected windowDidExitFullscreen if the window
|
||||||
|
* failed to become fullscreen.
|
||||||
|
*
|
||||||
|
* Since something went wrong and the current state is unknown, dump any pending events.
|
||||||
|
*/
|
||||||
- (void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification
|
- (void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification
|
||||||
{
|
{
|
||||||
SDL_Window *window = _data.window;
|
[self clearAllPendingWindowOperations];
|
||||||
|
|
||||||
if (window->is_destroying) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWindowStyle(window, GetWindowStyle(window));
|
|
||||||
|
|
||||||
[self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
|
|
||||||
isFullscreenSpace = NO;
|
|
||||||
inFullscreenTransition = NO;
|
|
||||||
|
|
||||||
[self windowDidExitFullScreen:nil];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
|
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
|
||||||
@@ -1371,6 +1372,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
SDL_Window *window = _data.window;
|
SDL_Window *window = _data.window;
|
||||||
|
|
||||||
inFullscreenTransition = NO;
|
inFullscreenTransition = NO;
|
||||||
|
isFullscreenSpace = YES;
|
||||||
[self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
|
[self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
|
||||||
|
|
||||||
if ([self windowOperationIsPending:PENDING_OPERATION_LEAVE_FULLSCREEN]) {
|
if ([self windowOperationIsPending:PENDING_OPERATION_LEAVE_FULLSCREEN]) {
|
||||||
@@ -1421,26 +1423,14 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
inFullscreenTransition = YES;
|
inFullscreenTransition = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This may be sent before windowDidExitFullscreen to signal that the window was
|
||||||
|
* dumped out of fullscreen with no animation.
|
||||||
|
*
|
||||||
|
* Since something went wrong and the state is unknown, dump any pending events.
|
||||||
|
*/
|
||||||
- (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
|
- (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
|
||||||
{
|
{
|
||||||
SDL_Window *window = _data.window;
|
[self clearAllPendingWindowOperations];
|
||||||
const NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
|
|
||||||
|
|
||||||
if (window->is_destroying) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_data.pending_position = NO;
|
|
||||||
_data.pending_size = NO;
|
|
||||||
window->last_position_pending = false;
|
|
||||||
window->last_size_pending = false;
|
|
||||||
|
|
||||||
SetWindowStyle(window, flags);
|
|
||||||
|
|
||||||
isFullscreenSpace = YES;
|
|
||||||
inFullscreenTransition = NO;
|
|
||||||
|
|
||||||
[self windowDidEnterFullScreen:nil];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidExitFullScreen:(NSNotification *)aNotification
|
- (void)windowDidExitFullScreen:(NSNotification *)aNotification
|
||||||
@@ -1449,16 +1439,24 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
NSWindow *nswindow = _data.nswindow;
|
NSWindow *nswindow = _data.nswindow;
|
||||||
|
|
||||||
inFullscreenTransition = NO;
|
inFullscreenTransition = NO;
|
||||||
|
isFullscreenSpace = NO;
|
||||||
_data.fullscreen_space_requested = NO;
|
_data.fullscreen_space_requested = NO;
|
||||||
|
|
||||||
/* As of macOS 10.15, the window decorations can go missing sometimes after
|
/* As of macOS 10.15, the window decorations can go missing sometimes after
|
||||||
certain fullscreen-desktop->exlusive-fullscreen->windowed mode flows
|
certain fullscreen-desktop->exclusive-fullscreen->windowed mode flows
|
||||||
sometimes. Making sure the style mask always uses the windowed mode style
|
sometimes. Making sure the style mask always uses the windowed mode style
|
||||||
when returning to windowed mode from a space (instead of using a pending
|
when returning to windowed mode from a space (instead of using a pending
|
||||||
fullscreen mode style mask) seems to work around that issue.
|
fullscreen mode style mask) seems to work around that issue.
|
||||||
*/
|
*/
|
||||||
SetWindowStyle(window, GetWindowWindowedStyle(window));
|
SetWindowStyle(window, GetWindowWindowedStyle(window));
|
||||||
|
|
||||||
|
/* This can happen if the window failed to enter fullscreen, as this
|
||||||
|
* may be called *before* windowDidFailToEnterFullScreen in that case.
|
||||||
|
*/
|
||||||
|
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||||
|
[self clearAllPendingWindowOperations];
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't recurse back into UpdateFullscreenMode() if this was hit in
|
/* Don't recurse back into UpdateFullscreenMode() if this was hit in
|
||||||
* a blocking transition, as the caller is already waiting in
|
* a blocking transition, as the caller is already waiting in
|
||||||
* UpdateFullscreenMode().
|
* UpdateFullscreenMode().
|
||||||
@@ -1503,9 +1501,10 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
if ([self windowOperationIsPending:PENDING_OPERATION_ZOOM]) {
|
if ([self windowOperationIsPending:PENDING_OPERATION_ZOOM]) {
|
||||||
[self clearPendingWindowOperation:PENDING_OPERATION_ZOOM];
|
[self clearPendingWindowOperation:PENDING_OPERATION_ZOOM];
|
||||||
[nswindow zoom:nil];
|
[nswindow zoom:nil];
|
||||||
|
_data.was_zoomed = !_data.was_zoomed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (![nswindow isZoomed]) {
|
if (!_data.was_zoomed) {
|
||||||
// Apply a pending window size, if not zoomed.
|
// Apply a pending window size, if not zoomed.
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
rect.origin.x = _data.pending_position ? window->pending.x : window->floating.x;
|
rect.origin.x = _data.pending_position ? window->pending.x : window->floating.x;
|
||||||
@@ -2125,6 +2124,7 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
window->internal = (SDL_WindowData *)CFBridgingRetain(data);
|
||||||
data.window = window;
|
data.window = window;
|
||||||
data.nswindow = nswindow;
|
data.nswindow = nswindow;
|
||||||
data.videodata = videodata;
|
data.videodata = videodata;
|
||||||
@@ -2245,7 +2245,6 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
|
|||||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER, SDL_METALVIEW_TAG);
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER, SDL_METALVIEW_TAG);
|
||||||
|
|
||||||
// All done!
|
// All done!
|
||||||
window->internal = (SDL_WindowData *)CFBridgingRetain(data);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3260,25 +3259,21 @@ bool Cocoa_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float op
|
|||||||
|
|
||||||
bool Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
bool Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = false;
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
/* The timeout needs to be high enough that animated fullscreen
|
const Uint64 timeout = SDL_GetTicksNS() + SDL_MS_TO_NS(2500);
|
||||||
* spaces transitions won't cause it to time out.
|
|
||||||
*/
|
|
||||||
Uint64 timeout = SDL_GetTicksNS() + SDL_MS_TO_NS(2000);
|
|
||||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
|
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
|
||||||
while (true) {
|
|
||||||
|
for (;;) {
|
||||||
SDL_PumpEvents();
|
SDL_PumpEvents();
|
||||||
|
|
||||||
if (SDL_GetTicksNS() >= timeout) {
|
result = ![data.listener hasPendingWindowOperation];
|
||||||
result = false;
|
if (result || SDL_GetTicksNS() >= timeout) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (![data.listener hasPendingWindowOperation]) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Small delay before going again.
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1005,6 +1005,27 @@ static void Emscripten_unset_drag_event_callbacks(SDL_WindowData *data)
|
|||||||
}, data->canvas_id);
|
}, data->canvas_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *Emscripten_GetKeyboardTargetElement()
|
||||||
|
{
|
||||||
|
const char *target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
|
||||||
|
|
||||||
|
if (!target || !*target) {
|
||||||
|
return EMSCRIPTEN_EVENT_TARGET_WINDOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_strcmp(target, "#none") == 0) {
|
||||||
|
return NULL;
|
||||||
|
} else if (SDL_strcmp(target, "#window") == 0) {
|
||||||
|
return EMSCRIPTEN_EVENT_TARGET_WINDOW;
|
||||||
|
} else if (SDL_strcmp(target, "#document") == 0) {
|
||||||
|
return EMSCRIPTEN_EVENT_TARGET_DOCUMENT;
|
||||||
|
} else if (SDL_strcmp(target, "#screen") == 0) {
|
||||||
|
return EMSCRIPTEN_EVENT_TARGET_SCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
|
void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
|
||||||
{
|
{
|
||||||
const char *keyElement;
|
const char *keyElement;
|
||||||
@@ -1033,12 +1054,8 @@ void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
|
|||||||
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, data, 0, Emscripten_HandlePointerLockChange);
|
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, data, 0, Emscripten_HandlePointerLockChange);
|
||||||
|
|
||||||
// Keyboard events are awkward
|
// Keyboard events are awkward
|
||||||
keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
|
keyElement = Emscripten_GetKeyboardTargetElement();
|
||||||
if (!keyElement || !*keyElement) {
|
if (keyElement) {
|
||||||
keyElement = EMSCRIPTEN_EVENT_TARGET_WINDOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_strcmp(keyElement, "#none") != 0) {
|
|
||||||
emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey);
|
emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey);
|
||||||
emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey);
|
emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey);
|
||||||
emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress);
|
emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress);
|
||||||
@@ -1094,12 +1111,8 @@ void Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
|
|||||||
|
|
||||||
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, 0, NULL);
|
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, 0, NULL);
|
||||||
|
|
||||||
target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
|
target = Emscripten_GetKeyboardTargetElement();
|
||||||
if (!target || !*target) {
|
if (target) {
|
||||||
target = EMSCRIPTEN_EVENT_TARGET_WINDOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_strcmp(target, "#none") != 0) {
|
|
||||||
emscripten_set_keydown_callback(target, NULL, 0, NULL);
|
emscripten_set_keydown_callback(target, NULL, 0, NULL);
|
||||||
emscripten_set_keyup_callback(target, NULL, 0, NULL);
|
emscripten_set_keyup_callback(target, NULL, 0, NULL);
|
||||||
emscripten_set_keypress_callback(target, NULL, 0, NULL);
|
emscripten_set_keypress_callback(target, NULL, 0, NULL);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "SDL_uikitvulkan.h"
|
#include "SDL_uikitvulkan.h"
|
||||||
#include "SDL_uikitmetalview.h"
|
#include "SDL_uikitmetalview.h"
|
||||||
#include "SDL_uikitmessagebox.h"
|
#include "SDL_uikitmessagebox.h"
|
||||||
|
#include "SDL_uikitpen.h"
|
||||||
|
|
||||||
#define UIKITVID_DRIVER_NAME "uikit"
|
#define UIKITVID_DRIVER_NAME "uikit"
|
||||||
|
|
||||||
@@ -170,6 +171,7 @@ static void UIKit_VideoQuit(SDL_VideoDevice *_this)
|
|||||||
|
|
||||||
SDL_QuitGCKeyboard();
|
SDL_QuitGCKeyboard();
|
||||||
SDL_QuitGCMouse();
|
SDL_QuitGCMouse();
|
||||||
|
UIKit_QuitPen(_this);
|
||||||
|
|
||||||
UIKit_QuitModes(_this);
|
UIKit_QuitModes(_this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1023,8 +1023,8 @@ static void relative_pointer_handle_relative_motion(void *data,
|
|||||||
dx = wl_fixed_to_double(dx_unaccel_w);
|
dx = wl_fixed_to_double(dx_unaccel_w);
|
||||||
dy = wl_fixed_to_double(dy_unaccel_w);
|
dy = wl_fixed_to_double(dy_unaccel_w);
|
||||||
} else {
|
} else {
|
||||||
dx = wl_fixed_to_double(dx_w);
|
dx = wl_fixed_to_double(dx_w) * window->pointer_scale.x;
|
||||||
dy = wl_fixed_to_double(dy_w);
|
dy = wl_fixed_to_double(dy_w) * window->pointer_scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SendMouseMotion(timestamp, window->sdlwindow, input->pointer_id, true, (float)dx, (float)dy);
|
SDL_SendMouseMotion(timestamp, window->sdlwindow, input->pointer_id, true, (float)dx, (float)dy);
|
||||||
@@ -1884,7 +1884,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
|||||||
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, input->keyboard_id, key, scancode, state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, input->keyboard_id, key, scancode, state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
|
||||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
if (has_text && !(SDL_GetModState() & SDL_KMOD_CTRL)) {
|
if (has_text && !(SDL_GetModState() & (SDL_KMOD_CTRL | SDL_KMOD_ALT))) {
|
||||||
if (!handled_by_ime) {
|
if (!handled_by_ime) {
|
||||||
SDL_SendKeyboardText(text);
|
SDL_SendKeyboardText(text);
|
||||||
}
|
}
|
||||||
@@ -3304,6 +3304,11 @@ bool Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *w
|
|||||||
return SDL_SetError("No pointer to confine");
|
return SDL_SetError("No pointer to confine");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The confinement region will be created when the window is mapped.
|
||||||
|
if (w->shell_surface_status != WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* A confine may already be active, in which case we should destroy it and
|
/* A confine may already be active, in which case we should destroy it and
|
||||||
* create a new one.
|
* create a new one.
|
||||||
*/
|
*/
|
||||||
@@ -3353,6 +3358,9 @@ bool Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *w
|
|||||||
wl_region_destroy(confine_rect);
|
wl_region_destroy(confine_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Commit the double-buffered confinement region.
|
||||||
|
wl_surface_commit(w->surface);
|
||||||
|
|
||||||
w->confined_pointer = confined_pointer;
|
w->confined_pointer = confined_pointer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -903,6 +903,7 @@ static SDL_MouseButtonFlags SDLCALL Wayland_GetGlobalMouseState(float *x, float
|
|||||||
int off_x, off_y;
|
int off_x, off_y;
|
||||||
|
|
||||||
result = viddata->input->buttons_pressed;
|
result = viddata->input->buttons_pressed;
|
||||||
|
SDL_GetMouseState(x, y);
|
||||||
SDL_RelativeToGlobalForWindow(focus, focus->x, focus->y, &off_x, &off_y);
|
SDL_RelativeToGlobalForWindow(focus, focus->x, focus->y, &off_x, &off_y);
|
||||||
*x += off_x;
|
*x += off_x;
|
||||||
*y += off_y;
|
*y += off_y;
|
||||||
|
|||||||
@@ -707,6 +707,9 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the pointer confinement region, if necessary.
|
||||||
|
Wayland_input_confine_pointer(wind->waylandData->input, wind->sdlwindow);
|
||||||
|
|
||||||
/* If the window was initially set to the suspended state, send the occluded event now,
|
/* If the window was initially set to the suspended state, send the occluded event now,
|
||||||
* as we don't want to mark the window as occluded until at least one frame has been submitted.
|
* as we don't want to mark the window as occluded until at least one frame has been submitted.
|
||||||
*/
|
*/
|
||||||
@@ -2299,8 +2302,8 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't send redundant fullscreen set/unset events.
|
// Don't send redundant fullscreen set/unset events.
|
||||||
if (fullscreen != wind->is_fullscreen) {
|
if (!!fullscreen != wind->is_fullscreen) {
|
||||||
wind->fullscreen_was_positioned = fullscreen;
|
wind->fullscreen_was_positioned = !!fullscreen;
|
||||||
SetFullscreen(window, fullscreen ? output : NULL);
|
SetFullscreen(window, fullscreen ? output : NULL);
|
||||||
} else if (wind->is_fullscreen) {
|
} else if (wind->is_fullscreen) {
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -620,7 +620,7 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL
|
|||||||
|
|
||||||
SDL_WindowData *windowdata = window->internal;
|
SDL_WindowData *windowdata = window->internal;
|
||||||
|
|
||||||
if (haveMotion) {
|
if (haveMotion && !windowdata->in_modal_loop) {
|
||||||
if (!isAbsolute) {
|
if (!isAbsolute) {
|
||||||
SDL_SendMouseMotion(timestamp, window, mouseID, true, (float)dx, (float)dy);
|
SDL_SendMouseMotion(timestamp, window, mouseID, true, (float)dx, (float)dy);
|
||||||
} else {
|
} else {
|
||||||
@@ -1640,7 +1640,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
POINT cursorPos;
|
POINT cursorPos;
|
||||||
GetCursorPos(&cursorPos);
|
GetCursorPos(&cursorPos);
|
||||||
ScreenToClient(hwnd, &cursorPos);
|
ScreenToClient(hwnd, &cursorPos);
|
||||||
PostMessage(hwnd, WM_MOUSEMOVE, 0, cursorPos.x | cursorPos.y << 16);
|
PostMessage(hwnd, WM_MOUSEMOVE, 0, cursorPos.x | (((Uint32)((Sint16)cursorPos.y)) << 16));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -1792,7 +1792,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!data->disable_move_size_events) {
|
if (!data->disable_move_size_events) {
|
||||||
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
|
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
|
||||||
ClientToScreen(hwnd, (LPPOINT) &rect);
|
ClientToScreen(hwnd, (LPPOINT) &rect);
|
||||||
ClientToScreen(hwnd, (LPPOINT) &rect + 1);
|
ClientToScreen(hwnd, (LPPOINT) &rect + 1);
|
||||||
|
|
||||||
@@ -1804,7 +1804,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Moving the window from one display to another can change the size of the window (in the handling of SDL_EVENT_WINDOW_MOVED), so we need to re-query the bounds
|
// Moving the window from one display to another can change the size of the window (in the handling of SDL_EVENT_WINDOW_MOVED), so we need to re-query the bounds
|
||||||
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
|
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
|
||||||
w = rect.right;
|
w = rect.right;
|
||||||
h = rect.bottom;
|
h = rect.bottom;
|
||||||
|
|
||||||
@@ -1859,6 +1859,15 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
{
|
{
|
||||||
if (wParam == (UINT_PTR)SDL_IterateMainCallbacks) {
|
if (wParam == (UINT_PTR)SDL_IterateMainCallbacks) {
|
||||||
SDL_OnWindowLiveResizeUpdate(data->window);
|
SDL_OnWindowLiveResizeUpdate(data->window);
|
||||||
|
|
||||||
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
|
#if 0 // This locks up the Windows compositor when called by Steam; disabling until we understand why
|
||||||
|
// Make sure graphics operations are complete for smooth refresh
|
||||||
|
if (data->videodata->DwmFlush) {
|
||||||
|
data->videodata->DwmFlush();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -2084,7 +2093,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
RECT rect;
|
RECT rect;
|
||||||
float x, y;
|
float x, y;
|
||||||
|
|
||||||
if (!GetClientRect(hwnd, &rect) || WIN_IsRectEmpty(&rect)) {
|
if (!GetClientRect(hwnd, &rect) || !WIN_WindowRectValid(&rect)) {
|
||||||
if (inputs) {
|
if (inputs) {
|
||||||
SDL_small_free(inputs, isstack);
|
SDL_small_free(inputs, isstack);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ static void WIN_DeleteDevice(SDL_VideoDevice *device)
|
|||||||
if (data->shcoreDLL) {
|
if (data->shcoreDLL) {
|
||||||
SDL_UnloadObject(data->shcoreDLL);
|
SDL_UnloadObject(data->shcoreDLL);
|
||||||
}
|
}
|
||||||
|
if (data->dwmapiDLL) {
|
||||||
|
SDL_UnloadObject(data->dwmapiDLL);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_DXGI_H
|
#ifdef HAVE_DXGI_H
|
||||||
if (data->pDXGIFactory) {
|
if (data->pDXGIFactory) {
|
||||||
@@ -184,6 +187,17 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
|
|||||||
} else {
|
} else {
|
||||||
SDL_ClearError();
|
SDL_ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->dwmapiDLL = SDL_LoadObject("DWMAPI.DLL");
|
||||||
|
if (data->dwmapiDLL) {
|
||||||
|
/* *INDENT-OFF* */ // clang-format off
|
||||||
|
data->DwmFlush = (HRESULT (WINAPI *)(void))SDL_LoadFunction(data->dwmapiDLL, "DwmFlush");
|
||||||
|
data->DwmEnableBlurBehindWindow = (HRESULT (WINAPI *)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind))SDL_LoadFunction(data->dwmapiDLL, "DwmEnableBlurBehindWindow");
|
||||||
|
data->DwmSetWindowAttribute = (HRESULT (WINAPI *)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute))SDL_LoadFunction(data->dwmapiDLL, "DwmSetWindowAttribute");
|
||||||
|
/* *INDENT-ON* */ // clang-format on
|
||||||
|
} else {
|
||||||
|
SDL_ClearError();
|
||||||
|
}
|
||||||
#endif // #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
#endif // #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
|
|
||||||
#ifdef HAVE_DXGI_H
|
#ifdef HAVE_DXGI_H
|
||||||
|
|||||||
@@ -374,6 +374,45 @@ typedef struct tagINPUTCONTEXT2
|
|||||||
} INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;
|
} INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Corner rounding support (Win 11+)
|
||||||
|
#ifndef DWMWA_WINDOW_CORNER_PREFERENCE
|
||||||
|
#define DWMWA_WINDOW_CORNER_PREFERENCE 33
|
||||||
|
#endif
|
||||||
|
typedef enum {
|
||||||
|
DWMWCP_DEFAULT = 0,
|
||||||
|
DWMWCP_DONOTROUND = 1,
|
||||||
|
DWMWCP_ROUND = 2,
|
||||||
|
DWMWCP_ROUNDSMALL = 3
|
||||||
|
} DWM_WINDOW_CORNER_PREFERENCE;
|
||||||
|
|
||||||
|
// Border Color support (Win 11+)
|
||||||
|
#ifndef DWMWA_BORDER_COLOR
|
||||||
|
#define DWMWA_BORDER_COLOR 34
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DWMWA_COLOR_DEFAULT
|
||||||
|
#define DWMWA_COLOR_DEFAULT 0xFFFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DWMWA_COLOR_NONE
|
||||||
|
#define DWMWA_COLOR_NONE 0xFFFFFFFE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Transparent window support
|
||||||
|
#ifndef DWM_BB_ENABLE
|
||||||
|
#define DWM_BB_ENABLE 0x00000001
|
||||||
|
#endif
|
||||||
|
#ifndef DWM_BB_BLURREGION
|
||||||
|
#define DWM_BB_BLURREGION 0x00000002
|
||||||
|
#endif
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD flags;
|
||||||
|
BOOL enable;
|
||||||
|
HRGN blur_region;
|
||||||
|
BOOL transition_on_maxed;
|
||||||
|
} DWM_BLURBEHIND;
|
||||||
|
|
||||||
// Private display data
|
// Private display data
|
||||||
|
|
||||||
struct SDL_VideoData
|
struct SDL_VideoData
|
||||||
@@ -420,6 +459,11 @@ struct SDL_VideoData
|
|||||||
BOOL (WINAPI *GetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
|
BOOL (WINAPI *GetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
|
||||||
BOOL (WINAPI *GetPointerPenInfo)(UINT32 pointerId, POINTER_PEN_INFO *penInfo);
|
BOOL (WINAPI *GetPointerPenInfo)(UINT32 pointerId, POINTER_PEN_INFO *penInfo);
|
||||||
|
|
||||||
|
SDL_SharedObject *dwmapiDLL;
|
||||||
|
/* *INDENT-OFF* */ // clang-format off
|
||||||
|
HRESULT (WINAPI *DwmFlush)(void);
|
||||||
|
HRESULT (WINAPI *DwmEnableBlurBehindWindow)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind);
|
||||||
|
HRESULT (WINAPI *DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
|
||||||
/* *INDENT-ON* */ // clang-format on
|
/* *INDENT-ON* */ // clang-format on
|
||||||
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
|
|
||||||
|
|||||||
@@ -38,10 +38,6 @@
|
|||||||
// Dropfile support
|
// Dropfile support
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
|
||||||
// DWM setting support
|
|
||||||
typedef HRESULT (WINAPI *DwmSetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
|
|
||||||
typedef HRESULT (WINAPI *DwmGetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
|
|
||||||
|
|
||||||
// Dark mode support
|
// Dark mode support
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UXTHEME_APPMODE_DEFAULT,
|
UXTHEME_APPMODE_DEFAULT,
|
||||||
@@ -80,46 +76,6 @@ typedef UxthemePreferredAppMode (WINAPI *SetPreferredAppMode_t)(UxthemePreferred
|
|||||||
typedef BOOL (WINAPI *SetWindowCompositionAttribute_t)(HWND, const WINDOWCOMPOSITIONATTRIBDATA *);
|
typedef BOOL (WINAPI *SetWindowCompositionAttribute_t)(HWND, const WINDOWCOMPOSITIONATTRIBDATA *);
|
||||||
typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *);
|
typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *);
|
||||||
|
|
||||||
// Corner rounding support (Win 11+)
|
|
||||||
#ifndef DWMWA_WINDOW_CORNER_PREFERENCE
|
|
||||||
#define DWMWA_WINDOW_CORNER_PREFERENCE 33
|
|
||||||
#endif
|
|
||||||
typedef enum {
|
|
||||||
DWMWCP_DEFAULT = 0,
|
|
||||||
DWMWCP_DONOTROUND = 1,
|
|
||||||
DWMWCP_ROUND = 2,
|
|
||||||
DWMWCP_ROUNDSMALL = 3
|
|
||||||
} DWM_WINDOW_CORNER_PREFERENCE;
|
|
||||||
|
|
||||||
// Border Color support (Win 11+)
|
|
||||||
#ifndef DWMWA_BORDER_COLOR
|
|
||||||
#define DWMWA_BORDER_COLOR 34
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DWMWA_COLOR_DEFAULT
|
|
||||||
#define DWMWA_COLOR_DEFAULT 0xFFFFFFFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DWMWA_COLOR_NONE
|
|
||||||
#define DWMWA_COLOR_NONE 0xFFFFFFFE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Transparent window support
|
|
||||||
#ifndef DWM_BB_ENABLE
|
|
||||||
#define DWM_BB_ENABLE 0x00000001
|
|
||||||
#endif
|
|
||||||
#ifndef DWM_BB_BLURREGION
|
|
||||||
#define DWM_BB_BLURREGION 0x00000002
|
|
||||||
#endif
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
DWORD flags;
|
|
||||||
BOOL enable;
|
|
||||||
HRGN blur_region;
|
|
||||||
BOOL transition_on_maxed;
|
|
||||||
} DWM_BLURBEHIND;
|
|
||||||
typedef HRESULT(WINAPI *DwmEnableBlurBehindWindow_t)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind);
|
|
||||||
|
|
||||||
// Windows CE compatibility
|
// Windows CE compatibility
|
||||||
#ifndef SWP_NOCOPYBITS
|
#ifndef SWP_NOCOPYBITS
|
||||||
#define SWP_NOCOPYBITS 0
|
#define SWP_NOCOPYBITS 0
|
||||||
@@ -447,7 +403,6 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
|
|||||||
data->videodata = videodata;
|
data->videodata = videodata;
|
||||||
data->initializing = true;
|
data->initializing = true;
|
||||||
data->last_displayID = window->last_displayID;
|
data->last_displayID = window->last_displayID;
|
||||||
data->dwma_border_color = DWMWA_COLOR_DEFAULT;
|
|
||||||
data->hint_erase_background_mode = GetEraseBackgroundModeHint();
|
data->hint_erase_background_mode = GetEraseBackgroundModeHint();
|
||||||
|
|
||||||
|
|
||||||
@@ -535,7 +490,7 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
|
|||||||
}
|
}
|
||||||
if (!(window->flags & SDL_WINDOW_MINIMIZED)) {
|
if (!(window->flags & SDL_WINDOW_MINIMIZED)) {
|
||||||
RECT rect;
|
RECT rect;
|
||||||
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
|
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
|
||||||
int w = rect.right;
|
int w = rect.right;
|
||||||
int h = rect.bottom;
|
int h = rect.bottom;
|
||||||
|
|
||||||
@@ -745,6 +700,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window, bool set_active_focus)
|
|||||||
|
|
||||||
bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
|
bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
|
||||||
{
|
{
|
||||||
|
SDL_VideoData *videodata = _this->internal;
|
||||||
HWND hwnd = (HWND)SDL_GetPointerProperty(create_props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, SDL_GetPointerProperty(create_props, "sdl2-compat.external_window", NULL));
|
HWND hwnd = (HWND)SDL_GetPointerProperty(create_props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, SDL_GetPointerProperty(create_props, "sdl2-compat.external_window", NULL));
|
||||||
HWND parent = NULL;
|
HWND parent = NULL;
|
||||||
if (hwnd) {
|
if (hwnd) {
|
||||||
@@ -806,24 +762,19 @@ bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
|
|||||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
// FIXME: does not work on all hardware configurations with different renders (i.e. hybrid GPUs)
|
// FIXME: does not work on all hardware configurations with different renders (i.e. hybrid GPUs)
|
||||||
if (window->flags & SDL_WINDOW_TRANSPARENT) {
|
if (window->flags & SDL_WINDOW_TRANSPARENT) {
|
||||||
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
|
if (videodata->DwmEnableBlurBehindWindow) {
|
||||||
if (handle) {
|
/* The region indicates which part of the window will be blurred and rest will be transparent. This
|
||||||
DwmEnableBlurBehindWindow_t DwmEnableBlurBehindWindowFunc = (DwmEnableBlurBehindWindow_t)SDL_LoadFunction(handle, "DwmEnableBlurBehindWindow");
|
is because the alpha value of the window will be used for non-blurred areas
|
||||||
if (DwmEnableBlurBehindWindowFunc) {
|
We can use (-1, -1, 0, 0) boundary to make sure no pixels are being blurred
|
||||||
/* The region indicates which part of the window will be blurred and rest will be transparent. This
|
*/
|
||||||
is because the alpha value of the window will be used for non-blurred areas
|
HRGN rgn = CreateRectRgn(-1, -1, 0, 0);
|
||||||
We can use (-1, -1, 0, 0) boundary to make sure no pixels are being blurred
|
DWM_BLURBEHIND bb;
|
||||||
*/
|
bb.flags = (DWM_BB_ENABLE | DWM_BB_BLURREGION);
|
||||||
HRGN rgn = CreateRectRgn(-1, -1, 0, 0);
|
bb.enable = TRUE;
|
||||||
DWM_BLURBEHIND bb;
|
bb.blur_region = rgn;
|
||||||
bb.flags = (DWM_BB_ENABLE | DWM_BB_BLURREGION);
|
bb.transition_on_maxed = FALSE;
|
||||||
bb.enable = TRUE;
|
videodata->DwmEnableBlurBehindWindow(hwnd, &bb);
|
||||||
bb.blur_region = rgn;
|
DeleteObject(rgn);
|
||||||
bb.transition_on_maxed = FALSE;
|
|
||||||
DwmEnableBlurBehindWindowFunc(hwnd, &bb);
|
|
||||||
DeleteObject(rgn);
|
|
||||||
}
|
|
||||||
SDL_UnloadObject(handle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,7 +1013,7 @@ void WIN_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *
|
|||||||
HWND hwnd = data->hwnd;
|
HWND hwnd = data->hwnd;
|
||||||
RECT rect;
|
RECT rect;
|
||||||
|
|
||||||
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
|
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
|
||||||
*w = rect.right;
|
*w = rect.right;
|
||||||
*h = rect.bottom;
|
*h = rect.bottom;
|
||||||
} else if (window->last_pixel_w && window->last_pixel_h) {
|
} else if (window->last_pixel_w && window->last_pixel_h) {
|
||||||
@@ -1265,42 +1216,20 @@ void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWM_WINDOW_CORNER_PREFERENCE WIN_UpdateCornerRoundingForHWND(HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
|
static void WIN_UpdateCornerRoundingForHWND(SDL_VideoDevice *_this, HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
|
||||||
{
|
{
|
||||||
DWM_WINDOW_CORNER_PREFERENCE oldPref = DWMWCP_DEFAULT;
|
SDL_VideoData *videodata = _this->internal;
|
||||||
|
if (videodata->DwmSetWindowAttribute) {
|
||||||
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
|
videodata->DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
|
||||||
if (handle) {
|
|
||||||
DwmGetWindowAttribute_t DwmGetWindowAttributeFunc = (DwmGetWindowAttribute_t)SDL_LoadFunction(handle, "DwmGetWindowAttribute");
|
|
||||||
DwmSetWindowAttribute_t DwmSetWindowAttributeFunc = (DwmSetWindowAttribute_t)SDL_LoadFunction(handle, "DwmSetWindowAttribute");
|
|
||||||
if (DwmGetWindowAttributeFunc && DwmSetWindowAttributeFunc) {
|
|
||||||
DwmGetWindowAttributeFunc(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &oldPref, sizeof(oldPref));
|
|
||||||
DwmSetWindowAttributeFunc(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_UnloadObject(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldPref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static COLORREF WIN_UpdateBorderColorForHWND(HWND hwnd, COLORREF colorRef)
|
static void WIN_UpdateBorderColorForHWND(SDL_VideoDevice *_this, HWND hwnd, COLORREF colorRef)
|
||||||
{
|
{
|
||||||
COLORREF oldPref = DWMWA_COLOR_DEFAULT;
|
SDL_VideoData *videodata = _this->internal;
|
||||||
|
if (videodata->DwmSetWindowAttribute) {
|
||||||
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
|
videodata->DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
|
||||||
if (handle) {
|
|
||||||
DwmGetWindowAttribute_t DwmGetWindowAttributeFunc = (DwmGetWindowAttribute_t)SDL_LoadFunction(handle, "DwmGetWindowAttribute");
|
|
||||||
DwmSetWindowAttribute_t DwmSetWindowAttributeFunc = (DwmSetWindowAttribute_t)SDL_LoadFunction(handle, "DwmSetWindowAttribute");
|
|
||||||
if (DwmGetWindowAttributeFunc && DwmSetWindowAttributeFunc) {
|
|
||||||
DwmGetWindowAttributeFunc(hwnd, DWMWA_BORDER_COLOR, &oldPref, sizeof(oldPref));
|
|
||||||
DwmSetWindowAttributeFunc(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_UnloadObject(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldPref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1311,7 +1240,7 @@ SDL_FullscreenResult WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window
|
|||||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||||
SDL_DisplayData *displaydata = display->internal;
|
SDL_DisplayData *displaydata = display->internal;
|
||||||
SDL_WindowData *data = window->internal;
|
SDL_WindowData *data = window->internal;
|
||||||
HWND hwnd = data->hwnd;
|
HWND hwnd = data ? data->hwnd : NULL;
|
||||||
MONITORINFO minfo;
|
MONITORINFO minfo;
|
||||||
DWORD style, styleEx;
|
DWORD style, styleEx;
|
||||||
HWND top;
|
HWND top;
|
||||||
@@ -1366,13 +1295,13 @@ SDL_FullscreenResult WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable corner rounding & border color (Windows 11+) so the window fills the full screen
|
// Disable corner rounding & border color (Windows 11+) so the window fills the full screen
|
||||||
data->windowed_mode_corner_rounding = WIN_UpdateCornerRoundingForHWND(hwnd, DWMWCP_DONOTROUND);
|
WIN_UpdateCornerRoundingForHWND(_this, hwnd, DWMWCP_DONOTROUND);
|
||||||
data->dwma_border_color = WIN_UpdateBorderColorForHWND(hwnd, DWMWA_COLOR_NONE);
|
WIN_UpdateBorderColorForHWND(_this, hwnd, DWMWA_COLOR_NONE);
|
||||||
} else {
|
} else {
|
||||||
BOOL menu;
|
BOOL menu;
|
||||||
|
|
||||||
WIN_UpdateCornerRoundingForHWND(hwnd, (DWM_WINDOW_CORNER_PREFERENCE)data->windowed_mode_corner_rounding);
|
WIN_UpdateCornerRoundingForHWND(_this, hwnd, DWMWCP_DEFAULT);
|
||||||
WIN_UpdateBorderColorForHWND(hwnd, data->dwma_border_color);
|
WIN_UpdateBorderColorForHWND(_this, hwnd, DWMWA_COLOR_DEFAULT);
|
||||||
|
|
||||||
/* Restore window-maximization state, as applicable.
|
/* Restore window-maximization state, as applicable.
|
||||||
Special care is taken to *not* do this if and when we're
|
Special care is taken to *not* do this if and when we're
|
||||||
|
|||||||
@@ -87,8 +87,6 @@ struct SDL_WindowData
|
|||||||
RECT initial_size_rect;
|
RECT initial_size_rect;
|
||||||
RECT cursor_clipped_rect; // last successfully committed clipping rect for this window
|
RECT cursor_clipped_rect; // last successfully committed clipping rect for this window
|
||||||
RECT cursor_ctrlock_rect; // this is Windows-specific, but probably does not need to be per-window
|
RECT cursor_ctrlock_rect; // this is Windows-specific, but probably does not need to be per-window
|
||||||
UINT windowed_mode_corner_rounding;
|
|
||||||
COLORREF dwma_border_color;
|
|
||||||
bool mouse_tracked;
|
bool mouse_tracked;
|
||||||
bool destroy_parent_with_window;
|
bool destroy_parent_with_window;
|
||||||
SDL_DisplayID last_displayID;
|
SDL_DisplayID last_displayID;
|
||||||
|
|||||||
@@ -977,7 +977,7 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
|
|||||||
X11_HandleModifierKeys(videodata, scancode, true, true);
|
X11_HandleModifierKeys(videodata, scancode, true, true);
|
||||||
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, true);
|
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, true);
|
||||||
|
|
||||||
if (*text) {
|
if (*text && !(SDL_GetModState() & (SDL_KMOD_CTRL | SDL_KMOD_ALT))) {
|
||||||
text[text_length] = '\0';
|
text[text_length] = '\0';
|
||||||
X11_ClearComposition(windowdata);
|
X11_ClearComposition(windowdata);
|
||||||
SDL_SendKeyboardText(text);
|
SDL_SendKeyboardText(text);
|
||||||
@@ -2113,6 +2113,7 @@ void X11_PumpEvents(SDL_VideoDevice *_this)
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO,
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO,
|
||||||
"Time out elapsed after mode switch on display %" SDL_PRIu32 " with no window becoming fullscreen; reverting", _this->displays[i]->id);
|
"Time out elapsed after mode switch on display %" SDL_PRIu32 " with no window becoming fullscreen; reverting", _this->displays[i]->id);
|
||||||
SDL_SetDisplayModeForDisplay(_this->displays[i], NULL);
|
SDL_SetDisplayModeForDisplay(_this->displays[i], NULL);
|
||||||
|
_this->displays[i]->internal->mode_switch_deadline_ns = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,13 +48,17 @@
|
|||||||
static const char g_MessageBoxFontLatin1[] =
|
static const char g_MessageBoxFontLatin1[] =
|
||||||
"-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
|
"-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
|
||||||
|
|
||||||
static const char g_MessageBoxFont[] =
|
static const char* g_MessageBoxFont[] = {
|
||||||
"-*-*-medium-r-normal--*-120-*-*-*-*-iso10646-1," // explicitly unicode (iso10646-1)
|
"-*-*-medium-r-normal--*-120-*-*-*-*-iso10646-1", // explicitly unicode (iso10646-1)
|
||||||
"-*-*-medium-r-*--*-120-*-*-*-*-iso10646-1," // explicitly unicode (iso10646-1)
|
"-*-*-medium-r-*--*-120-*-*-*-*-iso10646-1", // explicitly unicode (iso10646-1)
|
||||||
"-*-*-*-*-*--*-*-*-*-*-*-iso10646-1," // just give me anything Unicode.
|
"-misc-*-*-*-*--*-*-*-*-*-*-iso10646-1", // misc unicode (fix for some systems)
|
||||||
"-*-*-medium-r-normal--*-120-*-*-*-*-iso8859-1," // explicitly latin1, in case low-ASCII works out.
|
"-*-*-*-*-*--*-*-*-*-*-*-iso10646-1", // just give me anything Unicode.
|
||||||
"-*-*-medium-r-*--*-120-*-*-*-*-iso8859-1," // explicitly latin1, in case low-ASCII works out.
|
"-*-*-medium-r-normal--*-120-*-*-*-*-iso8859-1", // explicitly latin1, in case low-ASCII works out.
|
||||||
"-*-*-*-*-*--*-*-*-*-*-*-iso8859-1"; // just give me anything latin1.
|
"-*-*-medium-r-*--*-120-*-*-*-*-iso8859-1", // explicitly latin1, in case low-ASCII works out.
|
||||||
|
"-misc-*-*-*-*--*-*-*-*-*-*-iso8859-1", // misc latin1 (fix for some systems)
|
||||||
|
"-*-*-*-*-*--*-*-*-*-*-*-iso8859-1", // just give me anything latin1.
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const SDL_MessageBoxColor g_default_colors[SDL_MESSAGEBOX_COLOR_COUNT] = {
|
static const SDL_MessageBoxColor g_default_colors[SDL_MESSAGEBOX_COLOR_COUNT] = {
|
||||||
{ 56, 54, 53 }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,
|
{ 56, 54, 53 }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,
|
||||||
@@ -200,13 +204,19 @@ static bool X11_MessageBoxInit(SDL_MessageBoxDataX11 *data, const SDL_MessageBox
|
|||||||
if (SDL_X11_HAVE_UTF8) {
|
if (SDL_X11_HAVE_UTF8) {
|
||||||
char **missing = NULL;
|
char **missing = NULL;
|
||||||
int num_missing = 0;
|
int num_missing = 0;
|
||||||
data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont,
|
int i_font;
|
||||||
&missing, &num_missing, NULL);
|
for (i_font = 0; g_MessageBoxFont[i_font]; ++i_font) {
|
||||||
if (missing) {
|
data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont[i_font],
|
||||||
X11_XFreeStringList(missing);
|
&missing, &num_missing, NULL);
|
||||||
|
if (missing) {
|
||||||
|
X11_XFreeStringList(missing);
|
||||||
|
}
|
||||||
|
if (data->font_set) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!data->font_set) {
|
if (!data->font_set) {
|
||||||
return SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
|
return SDL_SetError("Couldn't load x11 message box font");
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -555,22 +555,73 @@ static XRRScreenResources *X11_GetScreenResources(Display *dpy, int screen)
|
|||||||
|
|
||||||
static void X11_CheckDisplaysMoved(SDL_VideoDevice *_this, Display *dpy)
|
static void X11_CheckDisplaysMoved(SDL_VideoDevice *_this, Display *dpy)
|
||||||
{
|
{
|
||||||
const int screen = DefaultScreen(dpy);
|
const int screencount = ScreenCount(dpy);
|
||||||
XRRScreenResources *res = X11_GetScreenResources(dpy, screen);
|
|
||||||
if (!res) {
|
SDL_DisplayID *displays = SDL_GetDisplays(NULL);
|
||||||
|
if (!displays) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DisplayID *displays = SDL_GetDisplays(NULL);
|
for (int screen = 0; screen < screencount; ++screen) {
|
||||||
if (displays) {
|
XRRScreenResources *res = X11_GetScreenResources(dpy, screen);
|
||||||
|
if (!res) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; displays[i]; ++i) {
|
for (int i = 0; displays[i]; ++i) {
|
||||||
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
|
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
|
||||||
const SDL_DisplayData *displaydata = display->internal;
|
const SDL_DisplayData *displaydata = display->internal;
|
||||||
X11_UpdateXRandRDisplay(_this, dpy, screen, displaydata->xrandr_output, res, display);
|
if (displaydata->screen == screen) {
|
||||||
|
X11_UpdateXRandRDisplay(_this, dpy, screen, displaydata->xrandr_output, res, display);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDL_free(displays);
|
X11_XRRFreeScreenResources(res);
|
||||||
}
|
}
|
||||||
X11_XRRFreeScreenResources(res);
|
SDL_free(displays);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void X11_CheckDisplaysRemoved(SDL_VideoDevice *_this, Display *dpy)
|
||||||
|
{
|
||||||
|
const int screencount = ScreenCount(dpy);
|
||||||
|
int num_displays = 0;
|
||||||
|
|
||||||
|
SDL_DisplayID *displays = SDL_GetDisplays(&num_displays);
|
||||||
|
if (!displays) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int screen = 0; screen < screencount; ++screen) {
|
||||||
|
XRRScreenResources *res = X11_GetScreenResources(dpy, screen);
|
||||||
|
if (!res) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int output = 0; output < res->noutput; output++) {
|
||||||
|
for (int i = 0; i < num_displays; ++i) {
|
||||||
|
if (!displays[i]) {
|
||||||
|
// We already removed this display from the list
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
|
||||||
|
const SDL_DisplayData *displaydata = display->internal;
|
||||||
|
if (displaydata->xrandr_output == res->outputs[output]) {
|
||||||
|
// This display is active, remove it from the list
|
||||||
|
displays[i] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
X11_XRRFreeScreenResources(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_displays; ++i) {
|
||||||
|
if (displays[i]) {
|
||||||
|
// This display wasn't in the XRandR list
|
||||||
|
SDL_DelVideoDisplay(displays[i], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_free(displays);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutputChangeNotifyEvent *ev)
|
static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutputChangeNotifyEvent *ev)
|
||||||
@@ -580,9 +631,12 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("XRROutputChangeNotifyEvent! [output=%u, crtc=%u, mode=%u, rotation=%u, connection=%u]", (unsigned int) ev->output, (unsigned int) ev->crtc, (unsigned int) ev->mode, (unsigned int) ev->rotation, (unsigned int) ev->connection);
|
printf("XRROutputChangeNotifyEvent! [output=%u, crtc=%u, mode=%u, rotation=%u, connection=%u]\n", (unsigned int) ev->output, (unsigned int) ev->crtc, (unsigned int) ev->mode, (unsigned int) ev->rotation, (unsigned int) ev->connection);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// XWayland doesn't always send output disconnected events
|
||||||
|
X11_CheckDisplaysRemoved(_this, ev->display);
|
||||||
|
|
||||||
displays = SDL_GetDisplays(NULL);
|
displays = SDL_GetDisplays(NULL);
|
||||||
if (displays) {
|
if (displays) {
|
||||||
for (i = 0; displays[i]; ++i) {
|
for (i = 0; displays[i]; ++i) {
|
||||||
|
|||||||
@@ -78,6 +78,23 @@ static bool X11_IsXWayland(Display *d)
|
|||||||
return X11_XQueryExtension(d, "XWAYLAND", &opcode, &event, &error) == True;
|
return X11_XQueryExtension(d, "XWAYLAND", &opcode, &event, &error) == True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool X11_CheckCurrentDesktop(const char *name)
|
||||||
|
{
|
||||||
|
SDL_Environment *env = SDL_GetEnvironment();
|
||||||
|
|
||||||
|
const char *desktopVar = SDL_GetEnvironmentVariable(env, "DESKTOP_SESSION");
|
||||||
|
if (desktopVar && SDL_strcasecmp(desktopVar, name) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
desktopVar = SDL_GetEnvironmentVariable(env, "XDG_CURRENT_DESKTOP");
|
||||||
|
if (desktopVar && SDL_strcasestr(desktopVar, name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_VideoDevice *X11_CreateDevice(void)
|
static SDL_VideoDevice *X11_CreateDevice(void)
|
||||||
{
|
{
|
||||||
SDL_VideoDevice *device;
|
SDL_VideoDevice *device;
|
||||||
@@ -256,8 +273,14 @@ static SDL_VideoDevice *X11_CreateDevice(void)
|
|||||||
device->system_theme = SDL_SystemTheme_Get();
|
device->system_theme = SDL_SystemTheme_Get();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT |
|
device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT;
|
||||||
VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS;
|
|
||||||
|
/* Openbox doesn't send the new window dimensions when entering fullscreen, so the events must be synthesized.
|
||||||
|
* This is otherwise not wanted, as it can break fullscreen window positioning on multi-monitor configurations.
|
||||||
|
*/
|
||||||
|
if (!X11_CheckCurrentDesktop("openbox")) {
|
||||||
|
device->device_caps |= VIDEO_DEVICE_CAPS_SENDS_DISPLAY_CHANGES;
|
||||||
|
}
|
||||||
|
|
||||||
data->is_xwayland = X11_IsXWayland(x11_display);
|
data->is_xwayland = X11_IsXWayland(x11_display);
|
||||||
if (data->is_xwayland) {
|
if (data->is_xwayland) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user