Squashed 'external/SDL/' changes from 95c3ee77c10..b7362850534

b7362850534 examples/renderer/08-rotating-textures: Fix compiler warning on MSVC .
37d62deca16 examples/renderer/10-geometry: Fixes and cleanups.
0758b2a0c4c examples: Added renderer/10-geometry
1a90e092623 examples: Added renderer/09-scaling-textures
4fdeb6861bd examples: a few renderer fixes.
66b92e95acf examples: renamed renderer sources to match other example directories.
ffcf372d275 examples: Added renderer/08-rotating-textures
0c7334cce39 examples: Added renderer/07-streaming-textures
2bd3d9cfb7b examples: Added renderer/06-textures
9d0b3eded61 examples: added renderer/05-rectangles
3413617cb64 examples: added renderer/04-points
b0e528cc88a Switched ifdef from negative to positive
97d1056e16d GPU: MSAA fixes (#10917)
254b36361e5 Add SDL_PRILL? format specifiers specifically for long long type.
6f80d47d64d Use hexidecimal code for ±
4392233007d Removed tabs from headers
89c6bc5f502 Prefer Vulkan even on Windows (#10912)
980b4ff6dbe GPU: Vulkan descriptor management rewrite (#10910)
fcb8a2c016c wayland: Fix animated cursor timing
ea2e2e451d1 Better fix for initializing Android environment variables
095fb5f5221 Fixed infinite recursion at startup on Android
88a01fbc964 testautomation_stdlib.c: fix -Wformat warnings from mingw with %lld/%llu
b4e2777820c examples/renderer/03-lines: Fix compiler warning on Visual Studio.
2e3e5abd7d4 examples/renderer/03-lines: use a gray background.
fd0ce75e2ea tests: Fix tests when run with the --high-pixel-density flag
745d5e4991d examples/renderer/03-lines: Make this less obnoxious to look at.
1b266ec13d3 examples: added renderer/03-lines
6771a6020da testcamera: don't enable verbose logging
594edb6bd29 Add Thrustmaster TMX VID & PID to wheel device list.
34c60113607 Fixed Windows build
d29a0e3f310 Fixed warning: no previous prototype for function
7a924b36aeb compile_shaders.sh shouldn't be in the SDL framework
1f727b61f3c Sync SDL3 wiki -> header
398dff7c259 Added support for the HORI licensed Steam Controller
481203c074d Fixed Xcode warnings
7edf7fad664 fix bool define when SDL_DEFINE_STDBOOL is defined:
ff90570a3cf define SDL_DEFINE_STDBOOL for gcc < 3

git-subtree-dir: external/SDL
git-subtree-split: b7362850534295f076c19f7f8bffa06e530d0968
This commit is contained in:
SimoneN64
2024-09-22 15:30:30 +02:00
parent 3a7f96fd99
commit a22ac9e1c8
60 changed files with 2597 additions and 1126 deletions

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Gaming.Desktop.x64">
@@ -691,6 +691,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_shield.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steamdeck.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_wii.c" />

View File

@@ -80,6 +80,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_shield.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steamdeck.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_wii.c" />

View File

@@ -569,6 +569,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_shield.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steamdeck.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_wii.c" />

View File

@@ -1229,6 +1229,9 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steamdeck.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>

View File

@@ -379,7 +379,6 @@
E479118F2BA9555500CE3B7F /* SDL_genericstorage.c in Sources */ = {isa = PBXBuildFile; fileRef = E479118A2BA9555500CE3B7F /* SDL_genericstorage.c */; };
E4A568B62AF763940062EEC4 /* SDL_sysmain_callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = E4A568B52AF763940062EEC4 /* SDL_sysmain_callbacks.c */; };
E4F257712C818FE200FCEAFC /* SDL_gpu.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F257702C818FE200FCEAFC /* SDL_gpu.h */; settings = {ATTRIBUTES = (Public, ); }; };
E4F257902C81903800FCEAFC /* compile_shaders.sh in Resources */ = {isa = PBXBuildFile; fileRef = E4F2577D2C81903800FCEAFC /* compile_shaders.sh */; };
E4F257912C81903800FCEAFC /* Metal_Blit.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F2577E2C81903800FCEAFC /* Metal_Blit.h */; };
E4F257922C81903800FCEAFC /* Metal_Blit.metal in Sources */ = {isa = PBXBuildFile; fileRef = E4F2577F2C81903800FCEAFC /* Metal_Blit.metal */; };
E4F257932C81903800FCEAFC /* SDL_gpu_metal.m in Sources */ = {isa = PBXBuildFile; fileRef = E4F257802C81903800FCEAFC /* SDL_gpu_metal.m */; };
@@ -544,6 +543,8 @@
F3FA5A232B59ACE000FEAD97 /* yuv_rgb_lsx.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FA5A1A2B59ACE000FEAD97 /* yuv_rgb_lsx.c */; };
F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */; };
F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */; };
F3FD042E2C9B755700824C4C /* SDL_hidapi_nintendo.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */; };
F3FD042F2C9B755700824C4C /* SDL_hidapi_steam_hori.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */; };
FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); };
/* End PBXBuildFile section */
@@ -937,7 +938,6 @@
E479118A2BA9555500CE3B7F /* SDL_genericstorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_genericstorage.c; sourceTree = "<group>"; };
E4A568B52AF763940062EEC4 /* SDL_sysmain_callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysmain_callbacks.c; sourceTree = "<group>"; };
E4F257702C818FE200FCEAFC /* SDL_gpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_gpu.h; path = SDL3/SDL_gpu.h; sourceTree = "<group>"; };
E4F2577D2C81903800FCEAFC /* compile_shaders.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = compile_shaders.sh; sourceTree = "<group>"; };
E4F2577E2C81903800FCEAFC /* Metal_Blit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metal_Blit.h; sourceTree = "<group>"; };
E4F2577F2C81903800FCEAFC /* Metal_Blit.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Metal_Blit.metal; sourceTree = "<group>"; };
E4F257802C81903800FCEAFC /* SDL_gpu_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_gpu_metal.m; sourceTree = "<group>"; };
@@ -1115,6 +1115,8 @@
F3FA5A1A2B59ACE000FEAD97 /* yuv_rgb_lsx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yuv_rgb_lsx.c; sourceTree = "<group>"; };
F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_lsx.h; sourceTree = "<group>"; };
F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_common.h; sourceTree = "<group>"; };
F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_hidapi_nintendo.h; sourceTree = "<group>"; };
F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_steam_hori.c; sourceTree = "<group>"; };
F59C710300D5CB5801000001 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ReadMe.txt; sourceTree = "<group>"; };
F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
@@ -1898,25 +1900,27 @@
A7D8A7BE23E2513E00DCD162 /* hidapi */ = {
isa = PBXGroup;
children = (
A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */,
F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */,
A7D8A7C923E2513E00DCD162 /* SDL_hidapi_gamecube.c */,
F3F07D59269640160074468B /* SDL_hidapi_luna.c */,
F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */,
F388C95428B5F6F600661ECF /* SDL_hidapi_ps3.c */,
A7D8A7C323E2513E00DCD162 /* SDL_hidapi_ps4.c */,
F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */,
A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */,
A75FDBC323EA380300529352 /* SDL_hidapi_rumble.h */,
A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */,
9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */,
F3984CCF25BCC92800374F43 /* SDL_hidapi_stadia.c */,
A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */,
F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */,
A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */,
A7D8A7C623E2513E00DCD162 /* SDL_hidapi_switch.c */,
F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */,
A7D8A7C223E2513E00DCD162 /* SDL_hidapi_xbox360.c */,
A7D8A7C823E2513E00DCD162 /* SDL_hidapi_xbox360w.c */,
A7D8A7C523E2513E00DCD162 /* SDL_hidapi_xboxone.c */,
A7D8A7C723E2513E00DCD162 /* SDL_hidapijoystick_c.h */,
A7D8A7C423E2513E00DCD162 /* SDL_hidapijoystick.c */,
A7D8A7C723E2513E00DCD162 /* SDL_hidapijoystick_c.h */,
);
path = hidapi;
sourceTree = "<group>";
@@ -2297,7 +2301,6 @@
E4F257812C81903800FCEAFC /* metal */ = {
isa = PBXGroup;
children = (
E4F2577D2C81903800FCEAFC /* compile_shaders.sh */,
E4F2577E2C81903800FCEAFC /* Metal_Blit.h */,
E4F2577F2C81903800FCEAFC /* Metal_Blit.metal */,
E4F257802C81903800FCEAFC /* SDL_gpu_metal.m */,
@@ -2671,6 +2674,7 @@
A7D8B26023E2514200DCD162 /* vulkan.h in Headers */,
A7D8B2B423E2514200DCD162 /* vulkan_android.h in Headers */,
A7D8B2A823E2514200DCD162 /* vulkan_core.h in Headers */,
F3FD042E2C9B755700824C4C /* SDL_hidapi_nintendo.h in Headers */,
F3A9AE9B2C8A13C100AAC390 /* SDL_pipeline_gpu.h in Headers */,
E41D20152BA9577D003073FA /* SDL_storage.h in Headers */,
F37E18522BA50E760098C111 /* SDL_dialog.h in Headers */,
@@ -2763,7 +2767,6 @@
files = (
F37A8E1A28405AA100C38E95 /* CMake in Resources */,
A75FDBB823E4CBC700529352 /* ReadMe.txt in Resources */,
E4F257902C81903800FCEAFC /* compile_shaders.sh in Resources */,
A75FDBB723E4CBC700529352 /* License.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -3003,6 +3006,7 @@
A7D8B42E23E2514300DCD162 /* SDL_syscond.c in Sources */,
A7D8AADA23E2514100DCD162 /* SDL_syshaptic.c in Sources */,
A7D8BAE523E2514500DCD162 /* e_exp.c in Sources */,
F3FD042F2C9B755700824C4C /* SDL_hidapi_steam_hori.c in Sources */,
A7D8BB8123E2514500DCD162 /* SDL_quit.c in Sources */,
F3FA5A232B59ACE000FEAD97 /* yuv_rgb_lsx.c in Sources */,
A7D8AEA623E2514100DCD162 /* SDL_cocoawindow.m in Sources */,

View File

@@ -120,8 +120,16 @@ macro(add_sdl_example_executable TARGET)
target_include_directories(${TARGET} PRIVATE "$<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>")
endmacro()
add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/renderer-clear.c)
add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/renderer-primitives.c)
add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/clear.c)
add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/primitives.c)
add_sdl_example_executable(renderer-lines SOURCES renderer/03-lines/lines.c)
add_sdl_example_executable(renderer-points SOURCES renderer/04-points/points.c)
add_sdl_example_executable(renderer-rectangles SOURCES renderer/05-rectangles/rectangles.c)
add_sdl_example_executable(renderer-textures SOURCES renderer/06-textures/textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-streaming-textures SOURCES renderer/07-streaming-textures/streaming-textures.c)
add_sdl_example_executable(renderer-rotating-textures SOURCES renderer/08-rotating-textures/rotating-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-scaling-textures SOURCES renderer/09-scaling-textures/scaling-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-geometry SOURCES renderer/10-geometry/geometry.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(audio-simple-playback SOURCES audio/01-simple-playback/simple-playback.c)
add_sdl_example_executable(audio-simple-playback-callback SOURCES audio/02-simple-playback-callback/simple-playback-callback.c)
add_sdl_example_executable(audio-load-wav SOURCES audio/03-load-wav/load-wav.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav)

View File

@@ -1,3 +1,7 @@
This example creates an SDL window and renderer, and then draws some lines,
rectangles and points to it every frame.
This is just a quick overview of simple drawing primitives; futher examples
will explore them in more detail.

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and then draws a something
roughly like a Christmas tree with nothing but lines, every frame.

View File

@@ -0,0 +1,93 @@
/*
* This example creates an SDL window and renderer, and then draws some lines
* to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/lines", 640, 480, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_srand(0); /* seed the random number generator */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
int i;
/* Lines (line segments, really) are drawn in terms of points: a set of
X and Y coordinates, one set for each end of the line.
(0, 0) is the top left of the window, and larger numbers go down
and to the right. This isn't how geometry works, but this is pretty
standard in 2D graphics. */
static const SDL_FPoint line_points[] = {
{ 100, 354 }, { 220, 230 }, { 140, 230 }, { 320, 100 }, { 500, 230 },
{ 420, 230 }, { 540, 354 }, { 400, 354 }, { 100, 354 }
};
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255); /* grey, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* You can draw lines, one at a time, like these brown ones... */
SDL_SetRenderDrawColor(renderer, 127, 49, 32, 255);
SDL_RenderLine(renderer, 240, 450, 400, 450);
SDL_RenderLine(renderer, 240, 356, 400, 356);
SDL_RenderLine(renderer, 240, 356, 240, 450);
SDL_RenderLine(renderer, 400, 356, 400, 450);
/* You can also draw a series of connected lines in a single batch... */
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderLines(renderer, line_points, SDL_arraysize(line_points));
/* here's a bunch of lines drawn out from a center point in a circle. */
/* we randomize the color of each line, so it functions as animation. */
for (i = 0; i < 360; i++) {
const float size = 30.0f;
const float x = 320.0f;
const float y = 95.0f - (size / 2.0f);
SDL_SetRenderDrawColor(renderer, SDL_rand(256), SDL_rand(256), SDL_rand(256), 255);
SDL_RenderLine(renderer, x, y, x + SDL_sinf((float) i) * size, y + SDL_cosf((float) i) * size);
}
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and then draws a bunch of
single points, moving across the screen.

View File

@@ -0,0 +1,118 @@
/*
* This example creates an SDL window and renderer, and then draws some points
* to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static Uint64 last_time = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define NUM_POINTS 500
#define MIN_PIXELS_PER_SECOND 30 /* move at least this many pixels per second. */
#define MAX_PIXELS_PER_SECOND 60 /* move this many pixels per second at most. */
/* (track everything as parallel arrays instead of a array of structs,
so we can pass the coordinates to the renderer in a single function call.) */
/* Points are plotted as a set of X and Y coordinates.
(0, 0) is the top left of the window, and larger numbers go down
and to the right. This isn't how geometry works, but this is pretty
standard in 2D graphics. */
static SDL_FPoint points[NUM_POINTS];
static float point_speeds[NUM_POINTS];
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
int i;
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/points", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_srand(0); /* seed the random number generator */
/* set up the data for a bunch of points. */
for (i = 0; i < SDL_arraysize(points); i++) {
points[i].x = SDL_randf() * ((float) WINDOW_WIDTH);
points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT);
point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND));
}
last_time = SDL_GetTicks();
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const Uint64 now = SDL_GetTicks();
const float elapsed = ((float) (now - last_time)) / 1000.0f; /* seconds since last iteration */
int i;
/* let's move all our points a little for a new frame. */
for (i = 0; i < SDL_arraysize(points); i++) {
const float distance = elapsed * point_speeds[i];
points[i].x += distance;
points[i].y += distance;
if ((points[i].x >= WINDOW_WIDTH) || (points[i].y >= WINDOW_HEIGHT)) {
/* off the screen; restart it elsewhere! */
if (SDL_rand(2)) {
points[i].x = SDL_randf() * ((float) WINDOW_WIDTH);
points[i].y = 0.0f;
} else {
points[i].x = 0.0f;
points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT);
}
point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND));
}
}
last_time = now;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); /* white, full alpha */
SDL_RenderPoints(renderer, points, SDL_arraysize(points)); /* draw all the points! */
/* You can also draw single points with SDL_RenderPoint(), but it's
cheaper (sometimes significantly so) to do them all at once. */
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and then draws a few
rectangles that change size each frame.

View File

@@ -0,0 +1,110 @@
/*
* This example creates an SDL window and renderer, and then draws some
* rectangles to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect rects[16];
const Uint64 now = SDL_GetTicks();
int i;
/* we'll have the rectangles grow and shrink over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Rectangles are comprised of set of X and Y coordinates, plus width and
height. (0, 0) is the top left of the window, and larger numbers go
down and to the right. This isn't how geometry works, but this is
pretty standard in 2D graphics. */
/* Let's draw a single rectangle (square, really). */
rects[0].x = rects[0].y = 100;
rects[0].w = rects[0].h = 100 + (100 * scale);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); /* red, full alpha */
SDL_RenderRect(renderer, &rects[0]);
/* Now let's draw several rectangles with one function call. */
for (i = 0; i < 3; i++) {
const float size = (i+1) * 50.0f;
rects[i].w = rects[i].h = size + (size * scale);
rects[i].x = (WINDOW_WIDTH - rects[i].w) / 2; /* center it. */
rects[i].y = (WINDOW_HEIGHT - rects[i].h) / 2; /* center it. */
}
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); /* green, full alpha */
SDL_RenderRects(renderer, rects, 3); /* draw three rectangles at once */
/* those were rectangle _outlines_, really. You can also draw _filled_ rectangles! */
rects[0].x = 400;
rects[0].y = 50;
rects[0].w = 100 + (100 * scale);
rects[0].h = 50 + (50 * scale);
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); /* blue, full alpha */
SDL_RenderFillRect(renderer, &rects[0]);
/* ...and also fill a bunch of rectangles at once... */
for (i = 0; i < SDL_arraysize(rects); i++) {
const float w = (float) (WINDOW_WIDTH / SDL_arraysize(rects));
const float h = i * 8.0f;
rects[i].x = i * w;
rects[i].y = WINDOW_HEIGHT - h;
rects[i].w = w;
rects[i].h = h;
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); /* white, full alpha */
SDL_RenderFillRects(renderer, rects, SDL_arraysize(rects));
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a
.bmp file, and then draws it a few times each frame.

View File

@@ -0,0 +1,125 @@
/*
* This example creates an SDL window and renderer, and then draws some
* textures to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load bitmap!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create static texture!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
/* we'll have some textures move around over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Just draw the static texture a few times. You can think of it like a
stamp, there isn't a limit to the number of times you can draw with it. */
/* top left */
dst_rect.x = (100.0f * scale);
dst_rect.y = 0.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* center this one. */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* bottom right. */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) - (100.0f * scale);
dst_rect.y = (float) (WINDOW_HEIGHT - texture_height);
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, then a streaming texture that
it will update every frame before drawing it to the screen.

View File

@@ -0,0 +1,107 @@
/*
* This example creates an SDL window and renderer, and then draws a streaming
* texture to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
#define TEXTURE_SIZE 150
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/streaming-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, TEXTURE_SIZE, TEXTURE_SIZE);
if (!texture) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create streaming texture!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
SDL_Surface *surface = NULL;
/* we'll have some color move around over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* To update a streaming texture, you need to lock it first. This gets you access to the pixels.
Note that this is considered a _write-only_ operation: the buffer you get from locking
might not acutally have the existing contents of the texture, and you have to write to every
locked pixel! */
/* You can use SDL_LockTexture() to get an array of raw pixels, but we're going to use
SDL_LockTextureToSurface() here, because it wraps that array in a temporary SDL_Surface,
letting us use the surface drawing functions instead of lighting up individual pixels. */
if (SDL_LockTextureToSurface(texture, NULL, &surface)) {
SDL_Rect r;
SDL_FillSurfaceRect(surface, NULL, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 0, 0)); /* make the whole surface black */
r.w = TEXTURE_SIZE;
r.h = TEXTURE_SIZE / 10;
r.x = 0;
r.y = (int) (((float) (TEXTURE_SIZE - r.h)) * ((scale + 1.0f) / 2.0f));
SDL_FillSurfaceRect(surface, &r, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 255, 0)); /* make a strip of the surface green */
SDL_UnlockTexture(texture); /* upload the changes (and frees the temporary surface)! */
}
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 66, 66, 66, 255); /* grey, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Just draw the static texture a few times. You can think of it like a
stamp, there isn't a limit to the number of times you can draw with it. */
/* Center this one. It'll draw the latest version of the texture we drew while it was locked. */
dst_rect.x = ((float) (WINDOW_WIDTH - TEXTURE_SIZE)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - TEXTURE_SIZE)) / 2.0f;
dst_rect.w = dst_rect.h = (float) TEXTURE_SIZE;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
file, and then draws it, rotating around the center of the screen.

View File

@@ -0,0 +1,111 @@
/*
* This example creates an SDL window and renderer, and then draws some
* rotated textures to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/rotating-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load bitmap!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create static texture!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FPoint center;
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
/* we'll have a texture rotate around over 2 seconds (2000 milliseconds). 360 degrees in a circle! */
const float rotation = (((float) ((int) (now % 2000))) / 2000.0f) * 360.0f;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Center this one, and draw it with some rotation so it spins! */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
/* rotate it around the center of the texture; you can rotate it from a different point, too! */
center.x = texture_width / 2.0f;
center.y = texture_height / 2.0f;
SDL_RenderTextureRotated(renderer, texture, NULL, &dst_rect, rotation, &center, SDL_FLIP_NONE);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
file, and then draws it, scaling it up and down.

View File

@@ -0,0 +1,108 @@
/*
* This example creates an SDL window and renderer, and then draws some
* textures to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/scaling-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load bitmap!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create static texture!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
/* we'll have the texture grow and shrink over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* center this one and make it grow and shrink. */
dst_rect.w = (float) texture_width + (texture_width * scale);
dst_rect.h = (float) texture_height + (texture_height * scale);
dst_rect.x = ((float) (WINDOW_WIDTH - dst_rect.w)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - dst_rect.h)) / 2.0f;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
file, and then draws geometry (arbitrary polygons) using it.

View File

@@ -0,0 +1,164 @@
/*
* This example creates an SDL window and renderer, and then draws some
* geometry (arbitrary polygons) to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/geometry", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load bitmap!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create static texture!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const Uint64 now = SDL_GetTicks();
/* we'll have the triangle grow and shrink over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
const float size = 200.0f + (200.0f * scale);
SDL_Vertex vertices[4];
int i;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Draw a single triangle with a different color at each vertex. Center this one and make it grow and shrink. */
/* You always draw triangles with this, but you can string triangles together to form polygons. */
SDL_zeroa(vertices);
vertices[0].position.x = ((float) WINDOW_WIDTH) / 2.0f;
vertices[0].position.y = (((float) WINDOW_HEIGHT) - size) / 2.0f;
vertices[0].color.r = 1.0f;
vertices[0].color.a = 1.0f;
vertices[1].position.x = (((float) WINDOW_WIDTH) + size) / 2.0f;
vertices[1].position.y = (((float) WINDOW_HEIGHT) + size) / 2.0f;
vertices[1].color.g = 1.0f;
vertices[1].color.a = 1.0f;
vertices[2].position.x = (((float) WINDOW_WIDTH) - size) / 2.0f;
vertices[2].position.y = (((float) WINDOW_HEIGHT) + size) / 2.0f;
vertices[2].color.b = 1.0f;
vertices[2].color.a = 1.0f;
SDL_RenderGeometry(renderer, NULL, vertices, 3, NULL, 0);
/* you can also map a texture to the geometry! Texture coordinates go from 0.0f to 1.0f. That will be the location
in the texture bound to this vertex. */
SDL_zeroa(vertices);
vertices[0].position.x = 10.0f;
vertices[0].position.y = 10.0f;
vertices[0].color.r = vertices[0].color.g = vertices[0].color.b = vertices[0].color.a = 1.0f;
vertices[0].tex_coord.x = 0.0f;
vertices[0].tex_coord.y = 0.0f;
vertices[1].position.x = 150.0f;
vertices[1].position.y = 10.0f;
vertices[1].color.r = vertices[1].color.g = vertices[1].color.b = vertices[1].color.a = 1.0f;
vertices[1].tex_coord.x = 1.0f;
vertices[1].tex_coord.y = 0.0f;
vertices[2].position.x = 10.0f;
vertices[2].position.y = 150.0f;
vertices[2].color.r = vertices[2].color.g = vertices[2].color.b = vertices[2].color.a = 1.0f;
vertices[2].tex_coord.x = 0.0f;
vertices[2].tex_coord.y = 1.0f;
SDL_RenderGeometry(renderer, texture, vertices, 3, NULL, 0);
/* Did that only draw half of the texture? You can do multiple triangles sharing some vertices,
using indices, to get the whole thing on the screen: */
/* Let's just move this over so it doesn't overlap... */
for (i = 0; i < 3; i++) {
vertices[i].position.x += 450;
}
/* we need one more vertex, since the two triangles can share two of them. */
vertices[3].position.x = 600.0f;
vertices[3].position.y = 150.0f;
vertices[3].color.r = vertices[0].color.g = vertices[0].color.b = vertices[0].color.a = 1.0f;
vertices[3].tex_coord.x = 1.0f;
vertices[3].tex_coord.y = 1.0f;
/* And an index to tell it to reuse some of the vertices between triangles... */
{
/* 4 vertices, but 6 actual places they used. Indices need less bandwidth to transfer and can reorder vertices easily! */
const int indices[] = { 0, 1, 2, 1, 2, 3 };
SDL_RenderGeometry(renderer, texture, vertices, 4, indices, SDL_arraysize(indices));
}
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -1654,6 +1654,17 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK"
/**
* A variable controlling whether the HIDAPI driver for HORI licensed Steam
* controllers should be used.
*
* This variable can be set to the following values: "0" - HIDAPI driver is
* not used "1" - HIDAPI driver is used
*
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
*/
#define SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI "SDL_JOYSTICK_HIDAPI_STEAM_HORI"
/**
* A variable controlling whether the HIDAPI driver for Nintendo Switch
* controllers should be used.

View File

@@ -123,7 +123,7 @@ typedef Uint32 SDL_Keycode;
#define SDLK_RIGHTBRACE 0x0000007du /* '}' */
#define SDLK_TILDE 0x0000007eu /* '~' */
#define SDLK_DELETE 0x0000007fu /* '\x7F' */
#define SDLK_PLUSMINUS 0x000000b1u /* '±' */
#define SDLK_PLUSMINUS 0x000000b1u /* '\xB1' */
#define SDLK_CAPSLOCK 0x40000039u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK) */
#define SDLK_F1 0x4000003au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1) */
#define SDLK_F2 0x4000003bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2) */

View File

@@ -38,6 +38,10 @@
#if defined(_MSC_VER) && (_MSC_VER < 1910)
#define SDL_DEFINE_STDBOOL
#endif
/* gcc-2.95 had non-standard stdbool.h */
#if defined(__GNUC__) && (__GNUC__ < 3)
#define SDL_DEFINE_STDBOOL
#endif
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#include <inttypes.h>
@@ -47,7 +51,7 @@
#ifdef SDL_DEFINE_STDBOOL
#ifndef __bool_true_false_are_defined
#define __bool_true_false_are_defined 1
#define bool int8_t
#define bool uint8_t
#define false 0
#define true 1
#endif
@@ -96,6 +100,25 @@ void *alloca(size_t);
# define SDL_SIZE_MAX ((size_t) -1)
#endif
#ifndef SDL_COMPILE_TIME_ASSERT
#if defined(__cplusplus)
/* Keep C++ case alone: Some versions of gcc will define __STDC_VERSION__ even when compiling in C++ mode. */
#if (__cplusplus >= 201103L)
#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x)
#endif
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202311L)
#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x)
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x)
#endif
#endif /* !SDL_COMPILE_TIME_ASSERT */
#ifndef SDL_COMPILE_TIME_ASSERT
/* universal, but may trigger -Wunused-local-typedefs */
#define SDL_COMPILE_TIME_ASSERT(name, x) \
typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1]
#endif
/**
* Check if the compiler supports a given builtin.
* Supported by virtually all clang versions and recent gcc. Use this
@@ -404,7 +427,7 @@ typedef Sint64 SDL_Time;
/* @} *//* Floating-point constants */
/* Make sure we have macros for printing width-based integers.
* <stdint.h> should define these but this is not true all platforms.
* <inttypes.h> should define these but this is not true all platforms.
* (for example win32) */
#ifndef SDL_PRIs64
#if defined(SDL_PLATFORM_WINDOWS)
@@ -478,6 +501,25 @@ typedef Sint64 SDL_Time;
#define SDL_PRIX32 "X"
#endif
#endif
/* Specifically for the `long long` -- SDL-specific. */
#ifdef SDL_PLATFORM_WINDOWS
SDL_COMPILE_TIME_ASSERT(longlong_size64, sizeof(long long) == 8); /* using I64 for windows - make sure `long long` is 64 bits. */
#define SDL_PRILL_PREFIX "I64"
#else
#define SDL_PRILL_PREFIX "ll"
#endif
#ifndef SDL_PRILLd
#define SDL_PRILLd SDL_PRILL_PREFIX "d"
#endif
#ifndef SDL_PRILLu
#define SDL_PRILLu SDL_PRILL_PREFIX "u"
#endif
#ifndef SDL_PRILLx
#define SDL_PRILLx SDL_PRILL_PREFIX "x"
#endif
#ifndef SDL_PRILLX
#define SDL_PRILLX SDL_PRILL_PREFIX "X"
#endif
/* Annotations to help code analysis tools */
#ifdef SDL_DISABLE_ANALYZE_MACROS
@@ -535,25 +577,6 @@ typedef Sint64 SDL_Time;
#endif
#endif /* SDL_DISABLE_ANALYZE_MACROS */
#ifndef SDL_COMPILE_TIME_ASSERT
#if defined(__cplusplus)
/* Keep C++ case alone: Some versions of gcc will define __STDC_VERSION__ even when compiling in C++ mode. */
#if (__cplusplus >= 201103L)
#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x)
#endif
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202311L)
#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x)
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x)
#endif
#endif /* !SDL_COMPILE_TIME_ASSERT */
#ifndef SDL_COMPILE_TIME_ASSERT
/* universal, but may trigger -Wunused-local-typedefs */
#define SDL_COMPILE_TIME_ASSERT(name, x) \
typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1]
#endif
/** \cond */
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
SDL_COMPILE_TIME_ASSERT(bool_size, sizeof(bool) == 1);

View File

@@ -1525,7 +1525,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL);
// This is only called at startup, to initialize the environment
SDL_setenv_unsafe(utfname, utfvalue, 1);
// Note that we call setenv() directly to avoid affecting SDL environments
setenv(utfname, utfvalue, 1);
(*env)->ReleaseStringUTFChars(env, name, utfname);
(*env)->ReleaseStringUTFChars(env, value, utfvalue);

View File

@@ -33,6 +33,8 @@
#include <limits.h>
#endif
#include "SDL_iostream_c.h"
/* This file provides a general interface for SDL to read and write
data sources. It can easily be extended to files, memory, etc.
*/

View File

@@ -155,12 +155,12 @@ static const SDL_GPUBootstrap *backends[] = {
#ifdef SDL_GPU_METAL
&MetalDriver,
#endif
#ifdef SDL_GPU_D3D12
&D3D12Driver,
#endif
#ifdef SDL_GPU_VULKAN
&VulkanDriver,
#endif
#ifdef SDL_GPU_D3D12
&D3D12Driver,
#endif
#ifdef SDL_GPU_D3D11
&D3D11Driver,
#endif
@@ -959,6 +959,10 @@ SDL_GPUTexture *SDL_CreateGPUTexture(
SDL_assert_release(!"For array textures: usage must not contain DEPTH_STENCIL_TARGET");
failed = true;
}
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) {
SDL_assert_release(!"For array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1");
failed = true;
}
}
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && createinfo->num_levels > 1) {
SDL_assert_release(!"For 2D multisample textures: num_levels must be 1");
@@ -1378,6 +1382,9 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
if (resolveTextureHeader->info.type == SDL_GPU_TEXTURETYPE_3D) {
SDL_assert_release(!"Resolve texture must not be of TEXTURETYPE_3D!");
}
if (!(resolveTextureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) {
SDL_assert_release(!"Resolve texture usage must include COLOR_TARGET!");
}
}
}
}

View File

@@ -2081,15 +2081,6 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
if (isMultisample) {
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
} else if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtvDesc.Texture2DMSArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DMSArray.ArraySize = 1;
}
} else {
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
@@ -2100,11 +2091,12 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else if (isMultisample) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
} else {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
}
}
res = ID3D11Device_CreateRenderTargetView(
renderer->device,

View File

@@ -2957,15 +2957,6 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
rtvDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
if (isMultisample) {
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
} else if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtvDesc.Texture2DMSArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DMSArray.ArraySize = 1;
}
} else {
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
@@ -2977,12 +2968,13 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else if (isMultisample) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
} else {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
rtvDesc.Texture2D.PlaneSlice = 0;
}
}
ID3D12Device_CreateRenderTargetView(
renderer->device,

View File

@@ -313,14 +313,6 @@ static NSUInteger SDLToMetal_SampleCount[] = {
8 // SDL_GPU_SAMPLECOUNT_8
};
static MTLTextureType SDLToMetal_TextureType[] = {
MTLTextureType2D, // SDL_GPU_TEXTURETYPE_2D
MTLTextureType2DArray, // SDL_GPU_TEXTURETYPE_2D_ARRAY
MTLTextureType3D, // SDL_GPU_TEXTURETYPE_3D
MTLTextureTypeCube, // SDL_GPU_TEXTURETYPE_CUBE
MTLTextureTypeCubeArray // SDL_GPU_TEXTURETYPE_CUBE_ARRAY
};
static SDL_GPUTextureFormat SwapchainCompositionToFormat[] = {
SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, // SDR
SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_LINEAR
@@ -330,6 +322,24 @@ static SDL_GPUTextureFormat SwapchainCompositionToFormat[] = {
static CFStringRef SwapchainCompositionToColorSpace[4]; // initialized on device creation
static MTLTextureType SDLToMetal_TextureType(SDL_GPUTextureType textureType, bool isMSAA)
{
switch (textureType) {
case SDL_GPU_TEXTURETYPE_2D:
return isMSAA ? MTLTextureType2DMultisample : MTLTextureType2D;
case SDL_GPU_TEXTURETYPE_2D_ARRAY:
return MTLTextureType2DArray;
case SDL_GPU_TEXTURETYPE_3D:
return MTLTextureType3D;
case SDL_GPU_TEXTURETYPE_CUBE:
return MTLTextureTypeCube;
case SDL_GPU_TEXTURETYPE_CUBE_ARRAY:
return MTLTextureTypeCubeArray;
default:
return MTLTextureType2D;
}
}
static MTLColorWriteMask SDLToMetal_ColorWriteMask(
SDL_GPUColorComponentFlags mask)
{
@@ -1198,10 +1208,12 @@ static void METAL_InsertDebugLabel(
[metalCommandBuffer->computeEncoder insertDebugSignpost:label];
} else {
// Metal doesn't have insertDebugSignpost for command buffers...
if (@available(macOS 10.13, *)) {
[metalCommandBuffer->handle pushDebugGroup:label];
[metalCommandBuffer->handle popDebugGroup];
}
}
}
}
static void METAL_PushDebugGroup(
@@ -1219,9 +1231,11 @@ static void METAL_PushDebugGroup(
} else if (metalCommandBuffer->computeEncoder) {
[metalCommandBuffer->computeEncoder pushDebugGroup:label];
} else {
if (@available(macOS 10.13, *)) {
[metalCommandBuffer->handle pushDebugGroup:label];
}
}
}
}
static void METAL_PopDebugGroup(
@@ -1237,9 +1251,11 @@ static void METAL_PopDebugGroup(
} else if (metalCommandBuffer->computeEncoder) {
[metalCommandBuffer->computeEncoder popDebugGroup];
} else {
if (@available(macOS 10.13, *)) {
[metalCommandBuffer->handle popDebugGroup];
}
}
}
}
// Resource Creation
@@ -1317,15 +1333,19 @@ static MetalTexture *METAL_INTERNAL_CreateTexture(
id<MTLTexture> texture;
MetalTexture *metalTexture;
textureDescriptor.textureType = SDLToMetal_TextureType[createinfo->type];
textureDescriptor.textureType = SDLToMetal_TextureType(createinfo->type, createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1);
textureDescriptor.pixelFormat = SDLToMetal_SurfaceFormat[createinfo->format];
// This format isn't natively supported so let's swizzle!
if (createinfo->format == SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM) {
textureDescriptor.swizzle = MTLTextureSwizzleChannelsMake(
MTLTextureSwizzleBlue,
if (@available(macOS 10.15, *)) {
textureDescriptor.swizzle = MTLTextureSwizzleChannelsMake(MTLTextureSwizzleBlue,
MTLTextureSwizzleGreen,
MTLTextureSwizzleRed,
MTLTextureSwizzleAlpha);
} else {
SDL_SetError("SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM is not supported");
return NULL;
}
}
textureDescriptor.width = createinfo->width;
@@ -2955,7 +2975,7 @@ static void METAL_BeginComputePass(
METAL_INTERNAL_TrackTexture(metalCommandBuffer, texture);
textureView = [texture->handle newTextureViewWithPixelFormat:SDLToMetal_SurfaceFormat[textureContainer->header.info.format]
textureType:SDLToMetal_TextureType[textureContainer->header.info.type]
textureType:SDLToMetal_TextureType(textureContainer->header.info.type, false)
levels:NSMakeRange(storageTextureBindings[i].mip_level, 1)
slices:NSMakeRange(storageTextureBindings[i].layer, 1)];
@@ -3409,7 +3429,9 @@ static Uint8 METAL_INTERNAL_CreateSwapchain(
windowData->layer = (__bridge CAMetalLayer *)(SDL_Metal_GetLayer(windowData->view));
windowData->layer.device = renderer->device;
#ifdef SDL_PLATFORM_MACOS
if (@available(macOS 10.13, *)) {
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
}
#endif
windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
#ifndef SDL_PLATFORM_TVOS
@@ -3632,7 +3654,9 @@ static bool METAL_SetSwapchainParameters(
METAL_Wait(driverData);
#ifdef SDL_PLATFORM_MACOS
if (@available(macOS 10.13, *)) {
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
}
#endif
windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
#ifndef SDL_PLATFORM_TVOS
@@ -3763,10 +3787,14 @@ static bool METAL_SupportsTextureFormat(
// Cube arrays are not supported on older iOS devices
if (type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
if (@available(macOS 10.15, *)) {
if (!([renderer->device supportsFamily:MTLGPUFamilyCommon2] ||
[renderer->device supportsFamily:MTLGPUFamilyApple4])) {
return false;
}
} else {
return false;
}
}
switch (format) {
@@ -3774,7 +3802,11 @@ static bool METAL_SupportsTextureFormat(
case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
if (@available(macOS 10.15, *)) {
return [renderer->device supportsFamily:MTLGPUFamilyApple1];
} else {
return false;
}
// Requires BC compression support
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM:

File diff suppressed because it is too large Load Diff

View File

@@ -1572,7 +1572,7 @@ int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char
}
memcpy(buf, descriptor_buf, copy_len);
return copy_len;
return (int)copy_len;
}
else {
register_device_error(dev, "Failed to get kIOHIDReportDescriptorKey property");

View File

@@ -806,6 +806,9 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
// The original SHIELD controller has a touchpad and plus/minus buttons as well
SDL_strlcat(mapping_string, "touchpad:b12,misc2:b13,misc3:b14", sizeof(mapping_string));
}
} else if (SDL_IsJoystickHoriSteamController(vendor, product)) {
/* The Wireless HORIPad for Steam has QAM, Steam, Capsense L/R Sticks, 2 rear buttons, and 2 misc buttons */
SDL_strlcat(mapping_string, "paddle1:b13,paddle2:b12,paddle3:b15,paddle4:b14,misc2:b11,misc3:b16,misc4:b17", sizeof(mapping_string));
} else {
switch (SDL_GetGamepadTypeFromGUID(guid, NULL)) {
case SDL_GAMEPAD_TYPE_PS4:

View File

@@ -366,6 +366,7 @@ static Uint32 initial_wheel_devices[] = {
MAKE_VIDPID(0x044f, 0xb65e), // Thrustmaster T500RS
MAKE_VIDPID(0x044f, 0xb664), // Thrustmaster TX (initial mode)
MAKE_VIDPID(0x044f, 0xb669), // Thrustmaster TX (active mode)
MAKE_VIDPID(0x044f, 0xb67f), // Thrustmaster TMX
MAKE_VIDPID(0x044f, 0xb691), // Thrustmaster TS-XW (initial mode)
MAKE_VIDPID(0x044f, 0xb692), // Thrustmaster TS-XW (active mode)
MAKE_VIDPID(0x0483, 0x0522), // Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U)
@@ -3099,6 +3100,11 @@ bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id)
return eType == k_eControllerType_SteamController || eType == k_eControllerType_SteamControllerV2;
}
bool SDL_IsJoystickHoriSteamController(Uint16 vendor_id, Uint16 product_id)
{
return vendor_id == USB_VENDOR_HORI && (product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER || product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER_BT);
}
bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);

View File

@@ -129,6 +129,9 @@ extern bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 produc
// Function to return whether a joystick is a Steam Controller
extern bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id);
// Function to return whether a joystick is a HORI Steam controller
extern bool SDL_IsJoystickHoriSteamController(Uint16 vendor_id, Uint16 product_id);
// Function to return whether a joystick is a Steam Deck
extern bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id);

View File

@@ -0,0 +1,415 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifdef SDL_JOYSTICK_HIDAPI
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
#include "../SDL_joystick_c.h"
#ifdef SDL_JOYSTICK_HIDAPI_STEAM_HORI
/* Define this if you want to log all packets from the controller */
/*#define DEBUG_HORI_PROTOCOL*/
#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
enum
{
SDL_GAMEPAD_BUTTON_HORI_QAM = 11,
SDL_GAMEPAD_BUTTON_HORI_FR,
SDL_GAMEPAD_BUTTON_HORI_FL,
SDL_GAMEPAD_BUTTON_HORI_M1,
SDL_GAMEPAD_BUTTON_HORI_M2,
SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_L,
SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_R,
SDL_GAMEPAD_NUM_HORI_BUTTONS
};
typedef struct
{
Uint8 last_state[USB_PACKET_LENGTH];
Uint64 sensor_ticks;
Uint32 last_tick;
bool wireless;
bool serial_needs_init;
} SDL_DriverSteamHori_Context;
static bool HIDAPI_DriverSteamHori_UpdateDevice(SDL_HIDAPI_Device *device);
static void HIDAPI_DriverSteamHori_RegisterHints(SDL_HintCallback callback, void *userdata)
{
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI, callback, userdata);
}
static void HIDAPI_DriverSteamHori_UnregisterHints(SDL_HintCallback callback, void *userdata)
{
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI, callback, userdata);
}
static bool HIDAPI_DriverSteamHori_IsEnabled(void)
{
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT));
}
static bool HIDAPI_DriverSteamHori_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
return SDL_IsJoystickHoriSteamController(vendor_id, product_id);
}
static bool HIDAPI_DriverSteamHori_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverSteamHori_Context *ctx;
ctx = (SDL_DriverSteamHori_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
return false;
}
device->context = ctx;
ctx->serial_needs_init = true;
HIDAPI_SetDeviceName(device, "Wireless HORIPAD For Steam");
return HIDAPI_JoystickConnected(device, NULL);
}
static int HIDAPI_DriverSteamHori_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
{
return -1;
}
static void HIDAPI_DriverSteamHori_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
{
}
static bool HIDAPI_DriverSteamHori_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
SDL_DriverSteamHori_Context *ctx = (SDL_DriverSteamHori_Context *)device->context;
SDL_AssertJoysticksLocked();
SDL_zeroa(ctx->last_state);
/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_GAMEPAD_NUM_HORI_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
joystick->nhats = 1;
ctx->wireless = device->product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER_BT;
if (ctx->wireless && device->serial) {
joystick->serial = SDL_strdup(device->serial);
ctx->serial_needs_init = false;
} else if (!ctx->wireless) {
// Need to actual read from the device to init the serial
HIDAPI_DriverSteamHori_UpdateDevice(device);
}
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 250.0f);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 250.0f);
return true;
}
static bool HIDAPI_DriverSteamHori_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
// Device doesn't support rumble
return SDL_Unsupported();
}
static bool HIDAPI_DriverSteamHori_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{
return SDL_Unsupported();
}
static Uint32 HIDAPI_DriverSteamHori_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return 0;
}
static bool HIDAPI_DriverSteamHori_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static bool HIDAPI_DriverSteamHori_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
{
return SDL_Unsupported();
}
static bool HIDAPI_DriverSteamHori_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
{
return true;
}
#undef clamp
#define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
#ifndef DEG2RAD
#define DEG2RAD(x) ((float)(x) * (float)(SDL_PI_F / 180.f))
#endif
//---------------------------------------------------------------------------
// Scale and clamp values to a range
//---------------------------------------------------------------------------
static float RemapValClamped(float val, float A, float B, float C, float D)
{
if (A == B) {
return (val - B) >= 0.0f ? D : C;
} else {
float cVal = (val - A) / (B - A);
cVal = clamp(cVal, 0.0f, 1.0f);
return C + (D - C) * cVal;
}
}
#define REPORT_HEADER_USB 0x07
#define REPORT_HEADER_BT 0x00
static void HIDAPI_DriverSteamHori_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverSteamHori_Context *ctx, Uint8 *data, int size)
{
Sint16 axis;
Uint64 timestamp = SDL_GetTicksNS();
// Make sure it's gamepad state and not OTA FW update info
if (data[0] != REPORT_HEADER_USB && data[0] != REPORT_HEADER_BT) {
/* We don't know how to handle this report */
return;
}
#define READ_STICK_AXIS(offset) \
(data[offset] == 0x80 ? 0 : (Sint16)HIDAPI_RemapVal((float)((int)data[offset] - 0x80), -0x80, 0xff - 0x80, SDL_MIN_SINT16, SDL_MAX_SINT16))
{
axis = READ_STICK_AXIS(1);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
axis = READ_STICK_AXIS(2);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
axis = READ_STICK_AXIS(3);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
axis = READ_STICK_AXIS(4);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
}
#undef READ_STICK_AXIS
if (ctx->last_state[5] != data[5]) {
Uint8 hat;
switch (data[5] & 0xF) {
case 0:
hat = SDL_HAT_UP;
break;
case 1:
hat = SDL_HAT_RIGHTUP;
break;
case 2:
hat = SDL_HAT_RIGHT;
break;
case 3:
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
hat = SDL_HAT_DOWN;
break;
case 5:
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
hat = SDL_HAT_LEFT;
break;
case 7:
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[5] & 0x10) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[5] & 0x20) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_QAM, ((data[5] & 0x40) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[5] & 0x80) != 0));
}
if (ctx->last_state[6] != data[6]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[6] & 0x01) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_M1 /* M1 */, ((data[6] & 0x02) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[6] & 0x04) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[6] & 0x08) != 0));
// TODO: can we handle the digital trigger mode? The data seems to come through analog regardless of the trigger state
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[6] & 0x40) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[6] & 0x80) != 0));
}
if (ctx->last_state[7] != data[7]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[7] & 0x01) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[7] & 0x02) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[7] & 0x04) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_M2, ((data[7] & 0x08) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_L, ((data[7] & 0x10) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_R, ((data[7] & 0x20) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_FR, ((data[7] & 0x40) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_FL, ((data[7] & 0x80) != 0));
}
if (!ctx->wireless && ctx->serial_needs_init) {
char serial[18];
(void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
data[38], data[39], data[40], data[41], data[42], data[43]);
joystick->serial = SDL_strdup(serial);
ctx->serial_needs_init = false;
}
#define READ_TRIGGER_AXIS(offset) \
(Sint16)(((int)data[offset] * 257) - 32768)
{
axis = READ_TRIGGER_AXIS(8);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
axis = READ_TRIGGER_AXIS(9);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
}
#undef READ_TRIGGER_AXIS
if (1) {
Uint64 sensor_timestamp;
float imu_data[3];
/* 16-bit timestamp */
Uint32 delta;
Uint16 tick = LOAD16(data[10],
data[11]);
if (ctx->last_tick < tick) {
delta = (tick - ctx->last_tick);
} else {
delta = (SDL_MAX_UINT16 - ctx->last_tick + tick + 1);
}
ctx->last_tick = tick;
ctx->sensor_ticks += delta;
/* Sensor timestamp is in 1us units, but there seems to be some issues with the values reported from the device */
sensor_timestamp = timestamp; // if the values were good we woudl call SDL_US_TO_NS(ctx->sensor_ticks);
const float accelScale = SDL_STANDARD_GRAVITY * 8 / 32768.0f;
const float gyroScale = DEG2RAD(2048);
imu_data[1] = RemapValClamped(-1.0f * LOAD16(data[12], data[13]), INT16_MIN, INT16_MAX, -gyroScale, gyroScale);
imu_data[2] = RemapValClamped(-1.0f * LOAD16(data[14], data[15]), INT16_MIN, INT16_MAX, -gyroScale, gyroScale);
imu_data[0] = RemapValClamped(-1.0f * LOAD16(data[16], data[17]), INT16_MIN, INT16_MAX, -gyroScale, gyroScale);
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, sensor_timestamp, imu_data, 3);
// SDL_Log("%u %f, %f, %f \n", data[0], imu_data[0], imu_data[1], imu_data[2] );
imu_data[2] = LOAD16(data[18], data[19]) * accelScale;
imu_data[1] = -1 * LOAD16(data[20], data[21]) * accelScale;
imu_data[0] = LOAD16(data[22], data[23]) * accelScale;
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, imu_data, 3);
}
if (ctx->last_state[24] != data[24]) {
bool bCharging = (data[24] & 0x10) != 0;
int percent = (data[24] & 0xF) * 10;
SDL_PowerState state;
if (bCharging) {
state = SDL_POWERSTATE_CHARGING;
} else if (ctx->wireless) {
state = SDL_POWERSTATE_ON_BATTERY;
} else {
state = SDL_POWERSTATE_CHARGED;
}
SDL_SendJoystickPowerInfo(joystick, state, percent);
}
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
}
static bool HIDAPI_DriverSteamHori_UpdateDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverSteamHori_Context *ctx = (SDL_DriverSteamHori_Context *)device->context;
SDL_Joystick *joystick = NULL;
Uint8 data[USB_PACKET_LENGTH];
int size = 0;
if (device->num_joysticks > 0) {
joystick = SDL_GetJoystickFromID(device->joysticks[0]);
} else {
return false;
}
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_HORI_PROTOCOL
HIDAPI_DumpPacket("Google Hori packet: size = %d", data, size);
#endif
if (!joystick) {
continue;
}
HIDAPI_DriverSteamHori_HandleStatePacket(joystick, ctx, data, size);
}
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}
return (size >= 0);
}
static void HIDAPI_DriverSteamHori_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
}
static void HIDAPI_DriverSteamHori_FreeDevice(SDL_HIDAPI_Device *device)
{
}
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamHori = {
SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI,
true,
HIDAPI_DriverSteamHori_RegisterHints,
HIDAPI_DriverSteamHori_UnregisterHints,
HIDAPI_DriverSteamHori_IsEnabled,
HIDAPI_DriverSteamHori_IsSupportedDevice,
HIDAPI_DriverSteamHori_InitDevice,
HIDAPI_DriverSteamHori_GetDevicePlayerIndex,
HIDAPI_DriverSteamHori_SetDevicePlayerIndex,
HIDAPI_DriverSteamHori_UpdateDevice,
HIDAPI_DriverSteamHori_OpenJoystick,
HIDAPI_DriverSteamHori_RumbleJoystick,
HIDAPI_DriverSteamHori_RumbleJoystickTriggers,
HIDAPI_DriverSteamHori_GetJoystickCapabilities,
HIDAPI_DriverSteamHori_SetJoystickLED,
HIDAPI_DriverSteamHori_SendJoystickEffect,
HIDAPI_DriverSteamHori_SetJoystickSensorsEnabled,
HIDAPI_DriverSteamHori_CloseJoystick,
HIDAPI_DriverSteamHori_FreeDevice,
};
#endif /* SDL_JOYSTICK_HIDAPI_STEAM_HORI */
#endif /* SDL_JOYSTICK_HIDAPI */

View File

@@ -67,6 +67,9 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
#ifdef SDL_JOYSTICK_HIDAPI_STEAM
&SDL_HIDAPI_DriverSteam,
#endif
#ifdef SDL_JOYSTICK_HIDAPI_STEAM_HORI
&SDL_HIDAPI_DriverSteamHori,
#endif
#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK
&SDL_HIDAPI_DriverSteamDeck,
#endif

View File

@@ -39,6 +39,7 @@
#define SDL_JOYSTICK_HIDAPI_XBOX360
#define SDL_JOYSTICK_HIDAPI_XBOXONE
#define SDL_JOYSTICK_HIDAPI_SHIELD
#define SDL_JOYSTICK_HIDAPI_STEAM_HORI
// Joystick capability definitions
#define SDL_JOYSTICK_CAP_MONO_LED 0x00000001
@@ -150,6 +151,7 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverWii;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamHori;
// Return true if a HID device is present and supported as a joystick of the given type
extern bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type);

View File

@@ -74,6 +74,8 @@
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS4 0x011c
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
#define USB_PRODUCT_HORI_STEAM_CONTROLLER 0x01AB
#define USB_PRODUCT_HORI_STEAM_CONTROLLER_BT 0x0196
#define USB_PRODUCT_LOGITECH_F310 0xc216
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
#define USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK 0x2218

View File

@@ -143,7 +143,7 @@ static bool AddFileDescriptorCloseActions(posix_spawn_file_actions_t *fa)
}
closedir(dir);
} else {
for (int fd = sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; --fd) {
for (int fd = (int)(sysconf(_SC_OPEN_MAX) - 1); fd > STDERR_FILENO; --fd) {
int flags = fcntl(fd, F_GETFD);
if (flags < 0 || (flags & FD_CLOEXEC)) {
continue;

View File

@@ -21,6 +21,7 @@
#include "SDL_internal.h"
#include "../SDL_hashtable.h"
#include "SDL_getenv_c.h"
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
#include "../core/windows/SDL_windows.h"

View File

@@ -115,7 +115,7 @@ static void Cocoa_HandlePenProximityEvent(SDL_CocoaWindowData *_data, NSEvent *e
static void Cocoa_HandlePenPointEvent(SDL_CocoaWindowData *_data, NSEvent *event)
{
const Uint32 timestamp = Cocoa_GetEventTimestamp([event timestamp]);
const Uint64 timestamp = Cocoa_GetEventTimestamp([event timestamp]);
Cocoa_PenHandle *handle = Cocoa_FindPenByDeviceID([event deviceID], [event pointingDeviceID]);
if (!handle) {
return;

View File

@@ -404,7 +404,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_TEXT_USERNAME:
textField.keyboardType = UIKeyboardTypeDefault;
if (@available(iOS 11.0, *)) {
if (@available(iOS 11.0, tvOS 11.0, *)) {
textField.textContentType = UITextContentTypeUsername;
} else {
textField.textContentType = nil;
@@ -412,7 +412,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN:
textField.keyboardType = UIKeyboardTypeDefault;
if (@available(iOS 11.0, *)) {
if (@available(iOS 11.0, tvOS 11.0, *)) {
textField.textContentType = UITextContentTypePassword;
} else {
textField.textContentType = nil;
@@ -421,7 +421,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE:
textField.keyboardType = UIKeyboardTypeDefault;
if (@available(iOS 11.0, *)) {
if (@available(iOS 11.0, tvOS 11.0, *)) {
textField.textContentType = UITextContentTypePassword;
} else {
textField.textContentType = nil;
@@ -433,7 +433,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN:
textField.keyboardType = UIKeyboardTypeNumberPad;
if (@available(iOS 12.0, *)) {
if (@available(iOS 12.0, tvOS 12.0, *)) {
textField.textContentType = UITextContentTypeOneTimeCode;
} else {
textField.textContentType = nil;
@@ -442,7 +442,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE:
textField.keyboardType = UIKeyboardTypeNumberPad;
if (@available(iOS 12.0, *)) {
if (@available(iOS 12.0, tvOS 12.0, *)) {
textField.textContentType = UITextContentTypeOneTimeCode;
} else {
textField.textContentType = nil;

View File

@@ -72,7 +72,8 @@ typedef struct
{
Wayland_SystemCursorFrame *frames;
struct wl_callback *frame_callback;
Uint64 last_frame_time_ms;
Uint64 last_frame_callback_time_ms;
Uint64 current_frame_time_ms;
Uint32 total_duration;
int num_frames;
int current_frame;
@@ -304,16 +305,20 @@ static void cursor_frame_done(void *data, struct wl_callback *cb, uint32_t time)
SDL_CursorData *c = (SDL_CursorData *)data;
const Uint64 now = SDL_GetTicks();
const Uint64 elapsed = (now - c->cursor_data.system.last_frame_time_ms) % c->cursor_data.system.total_duration;
const Uint64 elapsed = (now - c->cursor_data.system.last_frame_callback_time_ms) % c->cursor_data.system.total_duration;
Uint64 advance = 0;
int next = c->cursor_data.system.current_frame;
wl_callback_destroy(cb);
c->cursor_data.system.frame_callback = wl_surface_frame(c->surface);
wl_callback_add_listener(c->cursor_data.system.frame_callback, &cursor_frame_listener, data);
c->cursor_data.system.current_frame_time_ms += elapsed;
// Calculate the next frame based on the elapsed duration.
for (Uint64 t = c->cursor_data.system.frames[next].duration; t <= elapsed; t += c->cursor_data.system.frames[next].duration) {
for (Uint64 t = c->cursor_data.system.frames[next].duration; t <= c->cursor_data.system.current_frame_time_ms; t += c->cursor_data.system.frames[next].duration) {
next = (next + 1) % c->cursor_data.system.num_frames;
advance = t;
// Make sure we don't end up in an infinite loop if a cursor has frame durations of 0.
if (!c->cursor_data.system.frames[next].duration) {
@@ -321,7 +326,8 @@ static void cursor_frame_done(void *data, struct wl_callback *cb, uint32_t time)
}
}
c->cursor_data.system.last_frame_time_ms = now;
c->cursor_data.system.current_frame_time_ms -= advance;
c->cursor_data.system.last_frame_callback_time_ms = now;
c->cursor_data.system.current_frame = next;
wl_surface_attach(c->surface, c->cursor_data.system.frames[next].wl_buffer, 0, 0);
if (wl_surface_get_version(c->surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) {
@@ -711,7 +717,8 @@ static bool Wayland_ShowCursor(SDL_Cursor *cursor)
// If more than one frame is available, create a frame callback to run the animation.
if (data->cursor_data.system.num_frames > 1) {
data->cursor_data.system.last_frame_time_ms = SDL_GetTicks();
data->cursor_data.system.last_frame_callback_time_ms = SDL_GetTicks();
data->cursor_data.system.current_frame_time_ms = 0;
data->cursor_data.system.current_frame = 0;
data->cursor_data.system.frame_callback = wl_surface_frame(data->surface);
wl_callback_add_listener(data->cursor_data.system.frame_callback, &cursor_frame_listener, data);

View File

@@ -1119,6 +1119,7 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
Thing *thing = NULL;
saw_event = true;
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(event)), event);
switch (event->type) {
case SDL_EVENT_MOUSE_MOTION:

View File

@@ -184,6 +184,20 @@ static const char *AudioChansToStr(const int channels)
return "?";
}
static void scale_mouse_coords(SDL_FPoint *p)
{
SDL_Window *window = SDL_GetMouseFocus();
if (window) {
int w, p_w;
float scale;
SDL_GetWindowSize(window, &w, NULL);
SDL_GetWindowSizeInPixels(window, &p_w, NULL);
scale = (float)p_w / (float)w;
p->x *= scale;
p->y *= scale;
}
}
static void loop(void)
{
int i, j;
@@ -228,6 +242,7 @@ static void loop(void)
}
if (SDL_GetMouseState(&p.x, &p.y) & SDL_BUTTON_LMASK) {
scale_mouse_coords(&p);
if (active_slider == -1) {
for (i = 0; i < NUM_SLIDERS; ++i) {
if (SDL_PointInRectFloat(&p, &sliders[i].area)) {

View File

@@ -714,6 +714,9 @@ static int SDLCALL stdlib_getsetenv(void *arg)
#endif
#endif
#define FMT_PRILLd "%" SDL_PRILLd
#define FMT_PRILLu "%" SDL_PRILLu
/**
* Call to SDL_sscanf
*/
@@ -781,7 +784,7 @@ static int SDLCALL stdlib_sscanf(void *arg)
SIZED_TEST_CASE(short, short, "%hd")
SIZED_TEST_CASE(long, long, "%ld")
SIZED_TEST_CASE(long long, long_long, "%lld")
SIZED_TEST_CASE(long long, long_long, FMT_PRILLd)
size_output = 123;
expected_size_output = ~((size_t)0);
@@ -1301,26 +1304,26 @@ static int SDLCALL stdlib_strtox(void *arg)
} while (0)
// infer decimal
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "\t 123abcxyz", 0, 123, 6); // skip leading space
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "+123abcxyz", 0, 123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "+123abcxyz", 0, 123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-123abcxyz", 0, -123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "9999999999999999999999999999999999999999abcxyz", 0, ullong_max, 40);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "\t 123abcxyz", 0, 123, 6); // skip leading space
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "+123abcxyz", 0, 123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "+123abcxyz", 0, 123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-123abcxyz", 0, -123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "9999999999999999999999999999999999999999abcxyz", 0, ullong_max, 40);
// infer hexadecimal
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "0x123abcxyz", 0, 0x123abc, 8);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "0X123ABCXYZ", 0, 0x123abc, 8); // uppercase X
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0x123abcxyz", 0, 0x123abc, 8);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0X123ABCXYZ", 0, 0x123abc, 8); // uppercase X
// infer octal
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "0123abcxyz", 0, 0123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0123abcxyz", 0, 0123, 4);
// arbitrary bases
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "00110011", 2, 51, 8);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-uvwxyz", 32, -991, 3);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "ZzZzZzZzZzZzZzZzZzZzZzZzZ", 36, ullong_max, 25);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "00110011", 2, 51, 8);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-uvwxyz", 32, -991, 3);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "ZzZzZzZzZzZzZzZzZzZzZzZzZ", 36, ullong_max, 25);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-0", 10, 0, 2);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", " - 1", 0, 0, 0); // invalid input
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-0", 10, 0, 2);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, " - 1", 0, 0, 0); // invalid input
// We know that SDL_strtol, SDL_strtoul and SDL_strtoll share the same code path as SDL_strtoull under the hood,
// so the most interesting test cases are those close to the bounds of the integer type.
@@ -1342,15 +1345,15 @@ static int SDLCALL stdlib_strtox(void *arg)
}
if (sizeof(long long) == 8) {
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "9223372036854775807", 10, 9223372036854775807LL, 19);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "9223372036854775808", 10, 9223372036854775807LL, 19);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "-9223372036854775808", 10, -9223372036854775807LL - 1, 20);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "-9223372036854775809", 10, -9223372036854775807LL - 1, 20);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "-9999999999999999999999999999999999999999", 10, -9223372036854775807LL - 1, 41);
STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "9223372036854775807", 10, 9223372036854775807LL, 19);
STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "9223372036854775808", 10, 9223372036854775807LL, 19);
STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-9223372036854775808", 10, -9223372036854775807LL - 1, 20);
STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-9223372036854775809", 10, -9223372036854775807LL - 1, 20);
STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-9999999999999999999999999999999999999999", 10, -9223372036854775807LL - 1, 41);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "18446744073709551615", 10, 18446744073709551615ULL, 20);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "18446744073709551616", 10, 18446744073709551615ULL, 20);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-18446744073709551615", 10, 1, 21);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLd, "18446744073709551615", 10, 18446744073709551615ULL, 20);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLd, "18446744073709551616", 10, 18446744073709551615ULL, 20);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLd, "-18446744073709551615", 10, 1, 21);
}
#undef STRTOX_TEST_CASE

View File

@@ -97,8 +97,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
renderer = state->renderers[0];
if (!renderer) {
/* SDL_Log("Couldn't create renderer: %s", SDL_GetError()); */

View File

@@ -33,17 +33,25 @@ static SDL_HitTestResult SDLCALL
hitTest(SDL_Window *window, const SDL_Point *pt, void *data)
{
int i;
int w, h;
int w, h, p_w;
SDL_Point adj_pt;
float scale;
SDL_GetWindowSize(window, &w, &h);
SDL_GetWindowSizeInPixels(window, &p_w, NULL);
scale = (float)p_w / (float)w;
adj_pt.x = (int)SDL_floorf(pt->x * scale);
adj_pt.y = (int)SDL_floorf(pt->y * scale);
for (i = 0; i < numareas; i++) {
if (SDL_PointInRect(pt, &areas[i])) {
if (SDL_PointInRect(&adj_pt, &areas[i])) {
SDL_Log("HIT-TEST: DRAGGABLE\n");
return SDL_HITTEST_DRAGGABLE;
}
}
SDL_GetWindowSize(window, &w, &h);
#define REPORT_RESIZE_HIT(name) \
{ \
SDL_Log("HIT-TEST: RESIZE_" #name "\n"); \

View File

@@ -211,6 +211,7 @@ static void loop(void *arg)
/* Check for events */
while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, done);
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(&event)), &event);
switch (event.type) {
case SDL_EVENT_MOUSE_BUTTON_DOWN:
mouse_begin_x = event.button.x;

View File

@@ -184,7 +184,7 @@ static void HandleMouseAdded(SDL_MouseID instance_id)
SDL_Window *window = state->windows[0];
int i, w = 0, h = 0;
SDL_GetWindowSize(window, &w, &h);
SDL_GetWindowSizeInPixels(window, &w, &h);
for (i = 0; i < SDL_arraysize(mice); ++i) {
MouseState *mouse_state = &mice[i];
@@ -237,7 +237,7 @@ static void HandleMouseMotion(SDL_MouseMotionEvent *event)
ActivateMouse(event->which);
SDL_GetWindowSize(window, &w, &h);
SDL_GetWindowSizeInPixels(window, &w, &h);
for (i = 0; i < SDL_arraysize(mice); ++i) {
MouseState *mouse_state = &mice[i];

View File

@@ -255,6 +255,7 @@ static void loop(void)
/* Check for events */
while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, &done);
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(&event)), &event);
switch (event.type) {
case SDL_EVENT_WINDOW_RESIZED:

View File

@@ -165,6 +165,7 @@ static void loop(void)
while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, &done);
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(&event)), &event);
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
SDL_Window *window = SDL_GetWindowFromEvent(&event);