Compare commits

...
Author SHA1 Message Date
Frank Praznik 8d604353a5 renderer: Always use the output size when updating the main view
The main view always reflects the size of the output, so don't use the dimensions of the currently bound render target texture when updating it, or it will reflect an incorrect size when the render target texture is unbound.

(cherry picked from commit 8aa5b97bb5)
2025-05-14 09:38:13 -07:00
Ryan C. Gordon 8410e11ecb wikiheaders: Man pages should escape apostrophe chars.
This prevents problems if one starts a line, which would cause it to be
interpreted as a command character.

Fixes #13038.

(cherry picked from commit 1f7aa16eae)
2025-05-14 11:41:14 -04:00
krizej 9f8161bf4a docs: improve man page generation
(cherry picked from commit a390f5716e)
2025-05-14 11:40:58 -04:00
Sam Lantinga c038d6f7f8 Updated to version 3.2.14 for release 2025-05-13 14:24:40 -07:00
Frank Praznik 2fff37fffc Revert "x11: Send key events for dead keys consumed by the IME"
This and its related commits introduced some bugs and quirks such as duplicated and delayed/missed key events that can't be easily worked around, so revert this for now.

This reverts commit 47162a4168.

(cherry picked from commit 1eeffc5933)
2025-05-13 09:22:13 -07:00
Frank Praznik 6feb86be71 Revert "x11: Filter out duplicate key presses when an IME is active"
This reverts commit f4813ca2cf.

(cherry picked from commit 3304d24bea)
2025-05-13 09:22:13 -07:00
Sam Lantinga ed22220bc6 Fixed crash if out of memory in the Vulkan GPU driver
(cherry picked from commit cd95152b2c)
2025-05-13 09:08:19 -07:00
Andrey Moura 219cb1a59d joystick: Fix linker error when building without virtual joystick support
SDL_VIRTUAL_JoystickDriver was referenced outside an #ifdef when setting is_virtual, which caused a linker error. I modified it so that is_virtual is set to false if virtual joystick support is not enabled.
2025-05-13 08:55:29 -07:00
Simon McVittie 71bd25a893 audio: Assert that all devices from device_hash are the appropriate type
The keys and values of device_hash are pairs
`(SDL_AudioDeviceID devid, void *dev)` where dev can be either a
`SDL_AudioDevice *` or a `SDL_LogicalAudioDevice *`, depending on
bit 1 of devid.

We can confirm that we have got this right by looking at the
instance_id member, because logical audio devices happen to start with
the devid, whereas physical devices start with a pointer which is
unlikely to match the devid by chance.

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 70b2d162e3)
2025-05-13 08:53:35 -07:00
Ryan C. Gordon 01ef4c46a1 audio: Fix SDL_GetAudioDeviceName() not working with logical devices.
Fixes #12977.

(cherry picked from commit 0a34279578)
2025-05-12 13:54:52 -04:00
yunline 64f728ec48 tray: Fix wrong fByPositon parameter of SetMenuItemInfoW in SDL_SetTrayEntryLabel
(cherry picked from commit 9a6f70d75a)
2025-05-12 08:40:44 -07:00
Mike Kosek ba10adf1fb Added rightx and righty
(cherry picked from commit 38da39c8c9)
2025-05-12 08:40:44 -07:00
Dominic Bolin c18aa99358 GPU Vulkan: set correct destination usage mode for storage buffer read/write bindings (#13009) 2025-05-11 16:12:37 -07:00
ManuBlack 3498412611 AAudio: Implemented sample frames hint
(cherry picked from commit c6e9d6cc79)
2025-05-11 16:06:13 -07:00
Ryan C. Gordon 8c1b3ff210 Revert "pulseaudio: cleanup TLS every time we finish a threaded-mainloop callback."
This reverts commit 3b91017682.

This apparently is cleaning up more threads than expected, so this needs a
rethink.

Fixes #12986.
Fixes https://github.com/libsdl-org/sdl2-compat/issues/486
Fixes https://github.com/libsdl-org/sdl2-compat/issues/482

(cherry picked from commit e1066ceea1)
2025-05-11 10:23:04 -07:00
Frank Praznik 1870052af6 x11: Fix the Openbox quirk flag
Openbox needs fullscreen size/position event synthesized, but does not send display changed events.

(cherry picked from commit 84308e7fba)
2025-05-10 15:50:48 -04:00
dbolin 3b1e3d5176 GPU Vulkan: fix for Swapchain Semaphore Reuse
(cherry picked from commit 6344712b04)
2025-05-10 07:56:07 -07:00
RipleyTom cdf26c6e97 Add hid_version and hid_version_str to renamed LIBUSB impl symbols
(cherry picked from commit e90f7ac4a8)
2025-05-10 07:45:37 -07:00
Evan Hemsley 9f1a1405a6 GPU: Special case to avoid assert on GenerateMipmaps (#12995)
(cherry picked from commit 86b206dadf)
2025-05-09 22:00:57 -07:00
Sam Lantinga 6e97d8d1b3 Fixed crash if WGI isn't correlated in RAWINPUT_JoystickRumble()
(cherry picked from commit 87fe9ef79b)
2025-05-08 15:39:50 -07:00
Sam Lantinga 9d9a24d325 Define illegal_instruction() when it will be actually used
(cherry picked from commit 29d2116495)
2025-05-08 12:50:08 -07:00
Sam Lantinga 0897f4a7d1 Backported Metal sampler improvements from main
Fixes https://github.com/libsdl-org/SDL/issues/12988
2025-05-08 10:22:17 -07:00
Sam Lantinga 5aec645191 Added GCController mapping for the 8BitDo SN30 Pro on macOS
(cherry picked from commit 2b57d58f7d)
2025-05-08 09:57:36 -07:00
Sam Lantinga 07c33068f3 Added GCController mapping for the 8BitDo Pro 2 on macOS
Fixes https://github.com/libsdl-org/SDL/issues/12987

(cherry picked from commit d157600d3d)
2025-05-08 09:49:46 -07:00
expikr d684e5d57e fix #12963
(cherry picked from commit 6b048f59d7)
2025-05-06 21:18:02 -07:00
Frank Praznik 219500d95c x11: Filter out duplicate key presses when an IME is active
IME text events can result in sending duplicate key press events, which will result in undesired repeated key presses. Since the events are exact duplicates, compare the serials to filter out redundant key down events.

(cherry picked from commit f4813ca2cf)
2025-05-06 18:21:39 -04:00
Frank Praznik 810addf7ae x11: Don't update grab on enter when the mouse is captured
The xserver will still send EnterNotify events while the pointer is captured, and the grab shouldn't be updated in these cases, as it will cause the capture to be lost.

(cherry picked from commit 33e5f4885a)
2025-05-06 14:50:16 -07:00
Frank Praznik 4ef077ca52 Revert "x11: Better handle XInput2 mouse tracking outside the window"
This reverts commit 8c733d1f7b.

(cherry picked from commit 1abac3ccc3)
2025-05-06 14:50:16 -07:00
Sam Clegg 7d2275c4dc [emscripten] Remove referenc to Module['createContext']
The Module interface is the one used by the outside world.  This code
is inside the module itself so can use the internal name, avoiding the
need to export this function on the Module at all.

See https://github.com/emscripten-core/emscripten/pull/24269

(cherry picked from commit 8e1f4bafb4)
2025-05-06 14:16:36 -07:00
Ivan Epifanov cbd8917047 VITA: fix audio playback
(cherry picked from commit 1dbb813316)
2025-05-06 12:55:34 -07:00
Frank Praznik c98a19401c x11: #ifdef the XRandR path in the message box code
The runtime check isn't sufficient as the functions are undefined if built without XRandR.

(cherry picked from commit c91f9f6968)
2025-05-05 11:16:03 -04:00
A. Wilcox 434836c480 cpuinfo: Use auxv for AltiVec on Linux if possible
The SIGILL handler is not very reliable and can cause crashes.

Linux provides the CPU's AltiVec support status in getauxval.

(cherry picked from commit 7490471796)
2025-05-04 13:53:10 -07:00
Sam Lantinga 50d02ad732 Updated to version 3.2.13 for development 2025-05-04 10:56:10 -07:00
Ozkan Sezer 5ac37a8ffc don't prototype strdup() for __clang_analyzer__ case in windows builds.
Fixes:  https://github.com/libsdl-org/SDL/issues/12948.
(cherry picked from commit 17bba029ba)
2025-05-04 10:36:33 -07:00
Sam Lantinga 7dd2915475 Updated to version 3.2.12 for release 2025-05-04 10:09:23 -07:00
Frank Praznik 0ae1ddee17 win32: Hide the borders when showing a fullscreen window
If it is known that the window will immediately enter fullscreen upon being shown, set the borderless style when showing the window to hide the borders, or they may linger in the background if the client takes some time to draw the first frame.

Unnecessarily calling ShowWindow with SW_RESTORE when applying the window flags must be suppressed in this case, or the borders can reappear in a weird, partial state.

(cherry picked from commit d73fe0bc53)
2025-05-02 14:22:14 -04:00
Sam Lantinga db4c7e47f1 Added support for the share button on the GameSir-K1 FLUX controller
(cherry picked from commit ab12b7cbba)
2025-05-02 10:15:39 -07:00
Sam Lantinga 362445460e Added support for the PowerA Battle Dragon Advanced Wireless Controller
(cherry picked from commit 1e6a25324c)
2025-05-02 10:01:42 -07:00
Ryan C. Gordon de5cb9db23 dialog: Cocoa backend should reactivate the app after the modal dialog.
Otherwise the window won't have focus until you click on it again. Calling
makeKeyAndOrderFront isn't enough to fix it, either.

This trick comes from a similar problem we solve in our
applicationDidFinishLaunching implementation: activate (give app focus to) the
system Dock, as something that definitely exists that isn't us and is harmless
to activate, and then activate us right afterwards. This unconfuses whatever
is getting confused inside Cocoa.

Fixes #12684.

(cherry picked from commit 57346f2ba8)
2025-05-02 01:54:56 -04:00
Ryan C. Gordon 418eab29eb uikit: Use SDL_RunOnMainThread instead of dispatch_sync for message boxes.
Reference Issue #12741.

(cherry picked from commit 193b0c8963)
2025-05-02 01:54:17 -04:00
Ryan C. Gordon 2f3d242183 dialog: Cocoa shouldn't crash if there's a '.' in the filters.
So something like "index.pb" will now accept any file with a ".pb" extension,
to make macOS happy. This seems like a reasonable tradeoff.

Other minor cleanups.

Fixes #12778.

(cherry picked from commit 691cc5bb5e)
2025-05-01 21:37:54 -07:00
Cameron Gutman 4ad6d18203 events: Add integer wheel fields for sdl2-compat
It's way simpler to just add them back to SDL3 than emulate them purely in sdl2-compat.

(cherry picked from commit 0447c2f3c3)
2025-05-01 22:51:54 -05:00
Temdog007 cd4a4f8a9f X11: Center Message Box on Multi Monitor Displays (#12819)
Use XRandr to find the position of the current screen to center the message box on that window

(cherry picked from commit 4ef8b6ce1b)
2025-05-01 13:39:26 -07:00
Frank Praznik a96e72da02 video: Store the preferred fullscreen display in a property for sdl2-compat
sdl2-compat will call SDL_GetDisplayForWindow() when querying the display to use for fullscreen, which won't always be correct if the backend can't actually reposition the window. When calling this function, get the ideal fullscreen display and store it in a property for retrieval by sdl2-compat.

(cherry picked from commit c5d5967c3a)
2025-05-01 11:25:03 -07:00
Sam Lantinga 337f012de2 Fixed right mouse button emulation when using a pen
Pen button 1 is typically used as right click. Pen button 2 (Wacom eraser) doesn't have a specific mapping, but we'll use middle click for now.

(cherry picked from commit e3df61b070)
2025-04-30 11:08:24 -07:00
Sam Lantinga 3c29b620e4 Fixed missing simulated mouse events using a Wacom tablet
The low 16-bits of the message extra info is an event sequence number when using the Wacom tablet with Windows Ink disabled. The high bits of normal mouse motion when using touch input match the touch signature, 0xFF515700. The high bits of raw input mouse motion when using touch input do not match that signature, so we have to check for the touch bit in that case.

Fixes https://github.com/libsdl-org/SDL/issues/12927

(cherry picked from commit 106ccc722e)
2025-04-30 11:08:24 -07:00
Sam Lantinga 579fc161f0 Fixed build
(cherry picked from commit 8ae962c904)
2025-04-29 19:57:15 -07:00
Sam Lantinga 22e968af4e Fixed right click mouse emulation for the Wacom tablet
The problems are two-fold. When this happens a WM_POINTERDOWN event is sent with IS_POINTER_INCONTACT_WPARAM() evaluating as true. So when SDL_SendPenButton() is sent for the barrel button, there is no pen in contact yet, so the right mouse button is sent. Then SDL_SendPenTouch() is sent, which generates a left button press event.

Fixes https://github.com/libsdl-org/SDL/issues/12926

(cherry picked from commit e04064350f)
2025-04-29 19:57:15 -07:00
Ryan C. Gordon e37e96cfff pen: Windows can't check WM_POINTER[DOWN|UP] for touches directly.
These events fire for other things, such as pressing a barrel button while
the pen is hovering.

The correct thing to do is check IS_POINTER_INCONTACT_WPARAM in the event.

If the pen is already touching or not, SDL_SendPenTouch() will do the right
thing, so it's safe to call it even if we're already in the right state.

(cherry picked from commit ea67133e4f)
2025-04-29 19:57:15 -07:00
Evan Hemsley 56c76c20a0 GPU: Validate that textures are not bound for both read and write on render passes (#12925)
(cherry picked from commit a163257295)
2025-04-29 16:53:45 -07:00
Evan Hemsley efd812c399 GPU Vulkan: Add locks for layout object lookups (#12924)
(cherry picked from commit e1a41c1c97)
2025-04-29 15:44:37 -07:00
Sam Lantinga b2b92bbe25 Removed timeout in SDL_RunOnMainThread()
Fixes https://github.com/libsdl-org/SDL/issues/12923

(cherry picked from commit 8abcc27535)
2025-04-29 08:58:54 -07:00
Sam Lantinga a29c67ac94 Always enable D3D12 GPU on Windows
This isn't dependent on the render subsystem

Fixes https://github.com/libsdl-org/SDL/issues/12922

(cherry picked from commit ef54c3bf18)
2025-04-29 08:53:40 -07:00
Cameron Gutman f88e0aaac0 events: Fix undefined behavior when disabling some event types
Shifting a signed int left by 31 is UB.

(cherry picked from commit 39d3148185)
2025-04-29 00:27:02 -05:00
Ozkan Sezer 29a4a4a5d1 tray, unix: make pointers g_object_ref and g_object_ref_sink static
Fixes:  https://github.com/libsdl-org/SDL/issues/12908.
(cherry picked from commit 016ba86f93)
2025-04-27 10:22:18 -07:00
Frank Praznik 01000c73b0 cocoa: Immediately update the mouse focus when showing/hiding a popup menu
When showing or hiding a popup menu, manually check and set the focus if the new topmost window under the cursor is an SDL window. Otherwise, the focus won't be updated until the cursor is actually moved.

(cherry picked from commit 6f5892e543)
2025-04-27 09:39:36 -04:00
Frank Praznik 1a5d1dfef0 x11: Better handle XInput2 mouse tracking outside the window
There is a quirk with XInput2 mouse capture that causes a leave event to be sent if the pointer moves out->in->out, which breaks mouse tracking outside the window. If the mouse leaves the window with buttons pressed, continue tracking it until the buttons are released.

(cherry picked from commit 8c733d1f7b)
2025-04-26 13:16:19 -04:00
Austin Almond 2c38143834 GDK: Handle ProjectDir with space
The call to compile_shaders_xbox.bat fails if ProjectDir contains a space. Wrapping the command in quotes fixes the issue.

(cherry picked from commit 14ae45c2b8)
2025-04-25 15:01:07 -07:00
Ryan C. Gordon c56a1c664c aaudio: We PlayDevice first and WaitDevice after; reduce semaphore count by 1.
Previously, we would WaitDevice first, but that would feed a silent buffer
to AAudio upfront, introducing latency. When this change was made, the
semaphore count should have been adjusted, since we're waiting on one less
buffer.

Fixes #12882.

(cherry picked from commit 2767c1a440)
2025-04-25 15:08:56 -04:00
Ryan C. Gordon 41cae64580 pipewire: Use a more specific stream name than "Audio Stream".
This info shows up in `pw-top` ...Gnome's sound preferences (etc) would
already show something more app-specific, but this command line tool shows
specific stream names.

(cherry picked from commit a9bee3c0bf)
2025-04-25 14:26:03 -04:00
Ryan C. Gordon c6dd2662c3 pulseaudio: cleanup TLS every time we finish a threaded-mainloop callback.
These callbacks run in a thread we don't control, but might call SDL_SetError,
which will claim a TLS slot that never gets otherwise deallocated. To prevent
the leak, finish each callback by explicitly freeing any thread-local data.

Fixes #12732.

(cherry picked from commit 3b91017682)
2025-04-25 14:25:51 -04:00
Ryan C. Gordon f48027cf12 audio: Tweak SDL_GetAudioDeviceName.
- Add checks that ObtainPhysicalAudioDevice() was previously doing
  (is subsystem initialized, is device valid).
- Remove optimizations that copy string to stack to release device_hash_lock
  before SDL_GetPersistentString is called. Probably not necessary, and made
  the code more complex.

(cherry picked from commit b28449a58c)
2025-04-25 08:12:52 -07:00
Anonymous Maarten fabbc8d183 cmake: use CMAKE_ANDROID_NDK variable as root of Android ndk
This variable is always defined when targeting Android:
- when using the toolchain file shipped along the ndk
  (using  -DCMAKE_TOOLCHAIN_FILE=$ENV{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake)
- when using the toolchain file provided by CMake
  (using -DCMAKE_SYSTEM_NAME=Android)

(cherry picked from commit 5b1e92ae88)
2025-04-25 07:59:05 -07:00
Frank Praznik a142e5ef7d cocoa: Popup menus always accept first click
(cherry picked from commit 09b2aae47e)
2025-04-25 09:36:12 -04:00
Sam Lantinga 825c0c7691 Reset the keyboard when entering a modal loop on Windows
Fixes https://github.com/libsdl-org/SDL/issues/12876

(cherry picked from commit da3c864d4c)
2025-04-24 13:58:56 -07:00
expikr dc30a00a26 use GetMessagePos instead of GetCursorPos
(cherry picked from commit a82f70dc21)
2025-04-24 13:27:42 -07:00
kiddkaffeine 5a05ef01ad Fix crash in UIKit indirect pointer handling
(cherry picked from commit 5cacdf2513)
2025-04-24 13:05:23 -07:00
Alynne 0237997e4d Add Padix Rockfire devices (#12884)
(cherry picked from commit 32bbabe2a5)
2025-04-24 11:28:48 -07:00
Robert Müller 4f90432a49 Emscripten: fix incorrect error check for WebGL context creation
According to the documentation and testing the `emscripten_webgl_create_context` function returns `0` on error as oppposed to a negative number. This was causing the error message to be empty when the later `emscripten_webgl_make_context_current` call fails given the invalid context.

See https://emscripten.org/docs/api_reference/html5.h.html#c.emscripten_webgl_create_context

(cherry picked from commit 7e1d4f843c)
2025-04-24 11:26:16 -07:00
expikr 0cd6942bfc defer clipcursor refresh unto pump finish
(cherry picked from commit dd625a6763)
2025-04-24 10:37:30 -07:00
expikr 1beb6fdedf pass ground-truth cursor pos to WIN_UpdateFocus
(cherry picked from commit c84c2aa2c4)
2025-04-24 10:37:30 -07:00
Frank Praznik 3b4472ecf7 x11: Handle size/position events arriving before state events
Xfce, unlike every other window manager in existence, sends ConfigureNotify events before PropertyNotify events when toggling the fullscreen and maximized window state. Check the window state when handling ConfigureNotify events, and defer emitting SDL size/position events until the corresponding PropertyNotify event arrives, since SDL and clients expect to get the window state before the new size and position.

(cherry picked from commit 11a3296a42)
2025-04-24 12:29:24 -04:00
Frank Praznik faed8b620c audio: Fix warning C4701: potentially uninitialized local variable 'isstack' used
This warning is actually wrong, as the variable is only used if the string pointer is valid, in which case it was initialized, but this is needed to quiet MSVC.

(cherry picked from commit fb940fff80)
2025-04-24 08:49:48 -07:00
Ryan C. Gordon 982b778e45 audio: SDL_GetAudioDeviceName() doesn't need a full device lock.
Fixes https://github.com/libsdl-org/sdl2-compat/issues/468

(cherry picked from commit e8bd9cc150)
2025-04-24 08:49:48 -07:00
Vicki Pfau 3a8f1cb7c5 Joystick: Add trigger rumble resend
This was already present for regular rumble to ensure that controllers would
continue rumbling for extended periods, but was missing for trigger rumble. I
don't know if this affects any controllers at the moment, but it's helpful for
future-proofing.

(cherry picked from commit ceb9fecfc1)
2025-04-24 08:48:19 -07:00
Logan Benjamin 3c2d7ecdd6 GPU D3D12 - Update to use typeless formats for depth buffer (#12701)
For a depth buffer in D3D12 that is also going to be used in a texture sampler, the creation (on an Intel HD 5500 igpu) fails. e.g. SDL_GPUTextureCreateInfo type = TEXTURE_2D, format = D32_FLOAT, usage = DEPTH_STENCIL_TARGET | SAMPLER

The error messages are:

D32_FLOAT
D3D12 ERROR: ID3D12Device::CreateShaderResourceView: The Format (0x29, R32_FLOAT) is invalid when creating a View; the
Resource was already created with a fully qualified Format, which is not castable (0x28, D32_FLOAT).

D24_UNORM
D3D12 ERROR: ID3D12Device::CreateShaderResourceView: For the resource format D24_UNORM_S8_UINT, when making a D3D view, the format name for the view can't be R24_UNORM_X8_TYPELESS.

I found this is because the texture format needs to be created as _TYPELESS, then the views (depth stencil view, shader resource view) should then be created as their respective types - e.g. texture = R32_TYPELESS, dsv = D32_FLOAT, srv = R32_FLOAT

Tested and working on:
NVidia RTX 3050 (D3D12 feature set 12_2)
Intel HD 5500 (D3D12 feature set 11_1)

(cherry picked from commit c81b62293a)
2025-04-23 16:30:47 -07:00
Petar Popovic 0834f1d6ce SDL_GetRectIntersectionFloat(): Allow rendering zero-sized srcrect
(cherry picked from commit 27b256022b)
2025-04-23 16:16:24 -07:00
Lucas Murray 6ce446b768 GPU: Make D3D12 debug layers optional
(cherry picked from commit d04b28926c)
2025-04-23 16:16:24 -07:00
Sam Lantinga e045edb567 Corrected documentation for SDL_SetGPUSwapchainParameters()
(cherry picked from commit 695cad459b)
2025-04-23 16:16:24 -07:00
Ozkan Sezer 6cd14660cf stb_image.h: apply mainstream PR/1736
Fix root-cause of CVE-2021-45340 : dereference of NULL ptr.
Patch authored by Henner Zeller <h.zeller@acm.org>
Mainstream pull request: https://github.com/nothings/stb/pull/1736

(cherry picked from commit b5ed0d0138)
2025-04-23 17:55:24 +03:00
Sam Lantinga f5ac58c9f4 Added tests to cover invalid surface blits
Reproduction case for https://github.com/libsdl-org/SDL/issues/12844

(cherry picked from commit 89d7d406ab)
2025-04-22 13:06:36 -07:00
Petar Popovic c1779ca4a5 SDL_BlitSurfaceScaled(): Do not divide by zero
(cherry picked from commit fe849f1572)
2025-04-22 13:06:35 -07:00
Petar Popovic 6d8309f72e SDL_BlitSurfaceScaled(): Do not blit if surfaces have no pixel data
(cherry picked from commit 8017d38adc)
2025-04-22 13:06:35 -07:00
Sam Lantinga cf95db46a7 Renamed SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8 to SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER
Typically we will name the property with the function that is used to set it, and document the range of values.

(cherry picked from commit 18fbe6a92f)
2025-04-22 10:28:43 -07:00
Petar Popovic b8abfeb7f3 SDL_BlitSurface() comment: Remove sentence about final blit rect being stored in srcrect and dstrect
(cherry picked from commit a696b108ac)
2025-04-22 10:21:54 -07:00
Sam Lantinga 014e24e1a8 Removed incorrect documentation for SDL_RenderViewportSet()
Closes https://github.com/libsdl-org/SDL/pull/12854

(cherry picked from commit c076b0d17f)
2025-04-22 10:17:57 -07:00
Cameron Gutman e42071a47c x11: Send key events for dead keys consumed by the IME
This matches the Wayland backend and what apps originally written for SDL2 are expecting.

(cherry picked from commit 47162a4168)
2025-04-22 09:18:46 -07:00
Sam Lantinga 1543f523b7 Updated documentation for SDL_HINT_GPU_DRIVER
(cherry picked from commit 3aed80cd82)
2025-04-22 08:58:58 -07:00
Frank Praznik f2d0e965fc wayland: Account for timer rollover when calculating the elapsed time for key repeats.
The 32-bit millisecond timer can roll over after about 49 days, so this needs to be accounted for.

(cherry picked from commit 5bd1578a45)
2025-04-22 10:46:34 -04:00
Frank Praznik f782278d20 cocoa: Use CGFLOAT_MAX for unbounded max window dimensions
(cherry picked from commit 10f51da28d)
2025-04-21 21:11:07 -04:00
Frank Praznik 3b17d08eb2 win32: Check internal data when positioning child windows
Under certain circumstances, processing events may try to position a child before it is fully initialized. Check the internal data before proceeding.

(cherry picked from commit 9da46bc37f)
2025-04-16 12:50:34 -04:00
Sam Lantinga 18d367afd2 Fixed process I/O redirection to NUL on Windows
(cherry picked from commit 4093e4a193)
2025-04-11 15:45:33 -07:00
Sam Lantinga 9a4faf9ab9 Add the CREATE_NO_WINDOW flag for background processes
Fixes https://github.com/libsdl-org/SDL/issues/12097

(cherry picked from commit c025fdbb7c)
2025-04-11 15:45:33 -07:00
Sam Lantinga cb0ba020d4 Don't reset the render target when invalidating GPU renderer cache state
Fixes https://github.com/libsdl-org/SDL/issues/12646

(cherry picked from commit f35a2736b7)
2025-04-11 09:24:38 -07:00
Sam Lantinga f705e2f9f7 Fixed conflict when linking both SDL and hidapi statically
Fixes https://github.com/libsdl-org/SDL/issues/12790

(cherry picked from commit 98e76d283f)
2025-04-10 09:58:13 -07:00
Patrick José Pereira e76bffa183 Add Turtle Beach VelocityOne
Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
(cherry picked from commit f6db5ba4c9)
2025-04-10 09:48:58 -07:00
Adam Kewley a4e19dc567 [Windows]: dialog: Add OFN_OVERWRITEPROMPT to save dialogs (#12782)
(cherry picked from commit 0add037803)
2025-04-08 21:34:23 -07:00
Sam Lantinga 4e1282617a Fixed non-XBox controllers being detected as Series X controllers
First make sure we have an XBox One controller before checking whether it's a Series X/S controller.

(cherry picked from commit 93ac1e6894)
2025-04-08 12:21:34 -07:00
Sam Lantinga f102ff16a2 Don't treat the Keychron K1 Pro System Control keyboard as a joystick
Fixes https://github.com/libsdl-org/SDL/issues/12758

(cherry picked from commit d29bb902f3)
2025-04-08 11:08:55 -07:00
Ozkan Sezer 50935a9d41 fix sdlgenblit.pl so that it actually matches the generated source
(cherry picked from commit b0a0d236d8)
2025-04-08 18:24:40 +03:00
Sam Lantinga a1dde664d1 Updated version documentation to match SDL 3.x practice
(cherry picked from commit cccad933a0)
2025-04-07 10:23:27 -07:00
Frank Praznik ba5325fba1 x11/wayland: Ignore redundant restore and fullscreen leave requests when showing the window
The window may be initially maximized or made fullscreen by the window manager for various reasons, such as automatically declaring a window that precisely fills the usable desktop space as maximized, or a "kiosk-mode" automatically making the window fullscreen.

Don't redundantly make restored or unset fullscreen calls when initially showing a window, or the expected state can be unset.

(cherry picked from commit adad7dcae0)
2025-04-07 12:38:12 -04:00
Frank Praznik e225a10ea8 x11: Only enable _NET_WM_SYNC_REQUEST for OpenGL windows
It doesn't work well with Vulkan, and Vulkan windows may not have the Vulkan flag set in all circumstances, so only enable it if we explicitly know that OpenGL is being requested instead.

(cherry picked from commit 646f1f243f)
2025-04-05 15:45:35 -04:00
Evan Hemsley c4fba75a12 GPU Vulkan: Clean up in Submit in headless mode (#12744)
(cherry picked from commit 33f90f2e41)
2025-04-04 14:27:53 -07:00
Lucas Murray 5b052e6f8c GPU: Add missing error code to VkErrorMessages()
(cherry picked from commit 906c6c7516)
2025-04-04 07:39:44 -07:00
Lucas Murray d89c3489f8 GPU: The D3D12 blit shaders are DXIL
(cherry picked from commit 205c34c62a)
2025-04-04 07:39:43 -07:00
Sam Lantinga a447863e4f Set a default shader entry point
The default should be the entrypoint generated by SDL_shadercross. That way it doesn't need to be hand-specified in the common workflow.

(cherry picked from commit dcb97a5f49)
2025-04-04 07:39:16 -07:00
Lucas Murray 34db21cea8 GPU: Don't pass null properties to SDL_CopyProperties()
(cherry picked from commit 300013cea7)
2025-04-04 07:36:30 -07:00
Evan Hemsley 943226edc1 GPU Vulkan: Fix recursive Submit calls causing defrag to fail (#12718)
---------

Co-authored-by: Sam Lantinga <slouken@libsdl.org>
(cherry picked from commit b53e7b4478)
2025-04-03 15:01:43 -07:00
Frank Praznik 281494676a x11: Send a restored event before entering fullscreen
Ensures that the maximized flag is cleared on fullscreen windows.

(cherry picked from commit ca613b9d8f)
2025-04-03 17:02:43 -04:00
Frank Praznik 413b55deb7 x11: Don't set the hidden flag when minimizing windows
On non-compositing window managers, XIconifyWindow can trigger map/unmap events, which would toggle the window hidden/shown state. This should not be done, as a hidden window in SDL is equivalent to a withdrawn window in X, and SDL will try to set/reset state when it is shown again.

Unless the window is explicitly being withdrawn via X11_HideWindow(), set unmapped windows to the minimized/occluded state, and send a restored event when mapped again.

(cherry picked from commit 667b706a93)
2025-04-03 16:53:33 -04:00
Sam Lantinga 8222513f63 Added special handling for SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY
This hint needs to persist outside of the normal application flow, so use the environment to set the initial value, and then save the value set via SDL_SetHint() after that.

Fixes https://github.com/libsdl-org/SDL/issues/12677

(cherry picked from commit 6bb16296b0)
2025-04-03 11:34:03 -07:00
Sam Lantinga 2dd20ce8e7 Fixed building for Xbox One
Fixes https://github.com/libsdl-org/SDL/issues/12714

(cherry picked from commit 756b455d3a)
2025-04-03 09:10:01 -07:00
SDL Wiki Bot d308df6d62 Sync SDL3 wiki -> header
[ci skip]

(cherry picked from commit 008690d016)
2025-04-03 08:54:27 -07:00
Sam Lantinga f51b88e6b5 Note that you might get a different size window than you expect
(cherry picked from commit df32827407)
2025-04-03 08:54:27 -07:00
Sam Lantinga 7cb0fa5c56 Fixed documentation for SDL_GL_*_SIZE
(cherry picked from commit ab34ea5a26)
2025-04-02 22:32:39 -07:00
Sam Lantinga 976c92a2fb Added support for the HORI Taiko No Tatsujin Drum Controller
(cherry picked from commit 82b245d13a)
2025-04-02 08:30:55 -07:00
Frank Praznik 15db51d7ff cocoa: Ignore both clicks and motion on tooltip windows
(cherry picked from commit ad2584813f)
2025-04-01 22:50:33 -04:00
Frank Praznik 4aa4e6a18e x11: Enable legacy synchronization for external window resize and move events
External windows often handle their own events, and SDL implicitly processing events during synchronization can be unexpected and cause issues. For requests that don't change the window state beyond size or position, use the legacy synchronization method that synthesizes events from the window attributes without processing events.

(cherry picked from commit 6e2d3c9b5d)
2025-04-01 21:34:34 -04:00
Sam Lantinga 0759f22a91 More clarification for high DPI support
(cherry picked from commit 4de396734d)
2025-03-31 18:53:57 -07:00
Sam Lantinga 02036ee643 Fixed texture colorspace when creating a texture from a surface
Fixes https://github.com/libsdl-org/SDL/issues/12691

(cherry picked from commit 36fc1c2c9c)
2025-03-31 18:50:45 -07:00
blukai 9109e05f3f fix vulkan vertex buffer indexing
this was causing problems when i was specifying non-zero buffer slots in
`SDL_BindGPUVertexBuffers`, `SDL_GPUVertexAttribute` and
`SDL_GPUVertexBufferDescription`.

`firstSlot + 1` is simply copied over from metal and d3d12 backends.

(cherry picked from commit 512485869c)
2025-03-31 18:42:03 -07:00
Sam Lantinga 2103451d00 Clarify high DPI support and best practices
(cherry picked from commit 2e494fda30)
2025-03-31 16:49:55 -07:00
Sam Lantinga b6db091d60 Fixed A/B/X/Y buttons on Nintendo 3DS
Fixes https://github.com/libsdl-org/SDL/issues/12690

(cherry picked from commit 44faac2921)
2025-03-31 15:38:16 -07:00
Sam Lantinga 9827653c38 Updated to version 3.2.11 for development 2025-03-31 13:54:19 -07:00
Sam Lantinga 877399b2b2 Updated to version 3.2.10 for release 2025-03-31 13:12:19 -07:00
Frank Praznik 3f059376ac wayland: Commit the confinement region upon creation
This may prevent the pointer from escaping small regions if moving quickly.

(cherry picked from commit 6b1d6bfbe7)
2025-03-31 11:59:29 -04:00
Frank Praznik 30a6d01cc5 wayland: Defer creating cursor confinement regions until the surface is mapped
Otherwise, the confinement area will be lost if the window is recreated when initializing the renderer.

(cherry picked from commit 266ee41c86)
2025-03-31 11:59:29 -04:00
SDL Wiki Bot b6fb47aa70 Sync SDL3 wiki -> header
[ci skip]

(cherry picked from commit cb1d79db39)
2025-03-31 08:53:19 -07:00
Vittorio Romeo 7ecae856e5 Update include/SDL3/SDL_power.h
Co-authored-by: Sam Lantinga <slouken@libsdl.org>
(cherry picked from commit 088ad66f70)
2025-03-31 08:53:19 -07:00
Vittorio Romeo 5db7694f22 Add performance disclaimer in SDL_GetPowerInfo documentation
(cherry picked from commit 032d696021)
2025-03-31 08:53:19 -07:00
Sam Lantinga 366294e1c5 Fixed build
(cherry picked from commit 0d04e9ea6a)
2025-03-30 21:35:22 -07:00
Sam Lantinga 4d966ff546 Set the alpha opaque when blending to an RGB format
Fixes the render_testRGBSurfaceNoAlpha automated test in sdl2-compat

(cherry picked from commit 7bb95bde49)
2025-03-30 21:30:04 -07:00
Sam Lantinga 6b665066f0 Added SIMD blitters for 8888 -> 8888 format conversion
(cherry picked from commit e20e27e1fb)
2025-03-30 21:29:48 -07:00
Frank Praznik 519011f271 x11: Popup positions after constraining are in the window-relative space, not global
(cherry picked from commit 210b317d8d)
2025-03-29 11:11:24 -07:00
Andrei Tsurkan 5c224a3221 fix missing AVFoundation in CMakeLists.txt
(cherry picked from commit f7a89d19c6)
2025-03-29 08:45:26 -07:00
Sam Lantinga 4b8c38e7ba Temporarily disable DwmFlush()
For some reason this locks up the Windows compositor when called by Steam. I'm disabling it for now until we understand why and whether this can cause issues for other applications as well.

(cherry picked from commit a23f97483f)
2025-03-28 20:32:28 -07:00
Cameron Gutman 16f6c1058c gamepad: Fix inability to disable SDL_EVENT_GAMEPAD_UPDATE_COMPLETE events
(cherry picked from commit 712c76fdc1)
2025-03-28 17:19:49 -05:00
Green Sky 7939309520 video: fix surface leak when duplicating mjpeg
(cherry picked from commit eb918af3dc)
2025-03-28 13:19:29 -07:00
Sam Lantinga cec6073085 Updated link to PSP Hello World
(cherry picked from commit 304cb742881c5da76d41f28181624f8c2aafa05a)
2025-03-27 12:19:51 -07:00
Frank Praznik a9f121f3f7 cocoa: Clear pending state on fullscreen switch failures
The window failing to enter/exit fullscreen notifications don't necessarily imply anything about the actual state of the window. On failure, dump pending events, and don't presume anything about the current window state, as it will be handled by subsequent enter/leave notifications.

(cherry picked from commit 09fff161e9)
2025-03-27 11:59:43 -04:00
Frank Praznik 361218ce15 cocoa: Re-add sync timeout
This should never happen, but it's a failsafe against future bugs or odd configurations

(cherry picked from commit 05d23cae73)
2025-03-27 11:59:09 -04:00
Ryan C. Gordon 04dcfada00 audio: Allow PipeWire and PulseAudio streams to migrate to other sinks.
SDL still manages hotplug and default device management here, but if a user
wants to use an external tool, such as `pactl move-sink-input`, to put it
onto a different device, they probably know what they're doing and we
shouldn't stop them.

If this turns out to have some unexpected consequences, though, we can revisit
the change.

Fixes https://github.com/libsdl-org/sdl2-compat/issues/367

(cherry picked from commit 4c035a1fd8)
2025-03-27 11:22:59 -04:00
Sam Lantinga d73ad0ef18 Don't send relative motion while in a modal loop
This fixes queuing up a bunch of relative motion events while moving or resizing a window.

(cherry picked from commit 2e61b41652)
2025-03-27 08:10:58 -07:00
Ryan C. Gordon a1b888f622 alsa: Don't start the hardware until the device thread is ready to do work.
Otherwise, in the time it takes the thread to start and other init tasks to
complete, we tend to get an underrun on some systems, which ALSA logs to
stderr.

So this is moved to an InitThread implementation, which runs from the device
thread, right before it begins its main loop.

Reference PR #12632.

(cherry picked from commit ae17b04c0d)
2025-03-26 15:01:04 -04:00
Ryan C. Gordon d6267afcb9 audio: Feed output devices immediately, instead of waiting upfront.
This prevents the waste of an initial buffer of audio on many backends, and is
hopefully harmless on all of them.

Reference PR #12632.

(cherry picked from commit 41636959d2)
2025-03-26 14:58:54 -04:00
Ryan C. Gordon b8325be9cf pulseaudio: Fixed typo in commented-out debug logging.
(cherry picked from commit 48d4104ecb)
2025-03-26 14:58:46 -04:00
Sam Lantinga e77ef86f09 Added mappings for the NSO N64/SEGA/SNES controllers
These are used on Linux when the HIDAPI driver isn't available.

(cherry picked from commit e28974124a)
2025-03-25 14:46:30 -07:00
Sam Lantinga 951ba597ed Fixed face buttons for the NSO SNES controller under the HIDAPI driver
(cherry picked from commit b88200b797)
2025-03-25 14:46:30 -07:00
Frank Praznik ab5e178dab Fix spelling mistake in documentation
(cherry picked from commit b45ed98ae9)
2025-03-25 12:39:54 -04:00
Frank Praznik 04dace6c75 x11: Send the _XWAYLAND_MAY_GRAB_KEYBOARD message when grabbing the keyboard
GNOME requires this to allow keyboard grabs on XWayland. Otherwise, XGrabKeyboard will still report success, but shortcuts won't be inhibited.

See https://gitlab.gnome.org/GNOME/mutter/-/commit/5f132f39750f684c3732b4346dec810cd218d609

(cherry picked from commit 716e33f106)
2025-03-25 12:36:35 -04:00
Frank Praznik 013918cd83 cocoa: Properly set the pending fullscreen spaces state when in a transition
(cherry picked from commit b520cde18f)
2025-03-24 23:26:00 -04:00
Carl Åstholm 996466e855 Check if GL_OES_EGL_image_external is supported before trying to use it
(cherry picked from commit dd9b9d4513)
2025-03-24 19:52:54 -07:00
Carl Åstholm 61e7878ac0 Document SDL_malloc alignment guarantees
(cherry picked from commit 7ec13a2ead)
2025-03-24 19:41:08 -07:00
Frank Praznik c067cb4e7d wayland: Fix global mouse position retrieval
(cherry picked from commit 8cb303126f)
2025-03-24 19:06:35 -04:00
Sam Lantinga 38697dd812 Fixed mixed trigger and body rumble for Xbox controllers on Windows
Fixes https://github.com/libsdl-org/SDL/issues/12095

(cherry picked from commit b6ca03611f)
2025-03-24 11:07:12 -07:00
Cameron Gutman f03572335a keyboard: Don't check text input on a null window
(cherry picked from commit c3a3a11db4)
2025-03-23 23:53:19 -05:00
Frank Praznik d8837edfa2 wayland: Scale accelerated relative pointer coordinates with emulated resolutions
The accelerated relative coordinates are always relative to the desktop resolution, and need to be scaled with emulated fullscreen resolutions for mouse movement to remain stable. Otherwise, pointer speeds will be too fast on emulated resolutions below the desktop resolution, and too slow on those above.

(cherry picked from commit 027df89ed3)
2025-03-22 14:36:05 -04:00
expikr e5f8043037 chore: rename integer mode field names
(cherry picked from commit f52f982b1e)
2025-03-22 09:37:33 -07:00
Sam Lantinga 134b57f6f5 Improve move/resize visual smoothness on Windows
Fixes https://github.com/libsdl-org/SDL/issues/12528

(cherry picked from commit 6b13d69105)
2025-03-21 16:47:29 -07:00
Marcin Serwin 072e760197 audio: hold floating point exceptions when using neon
(cherry picked from commit 4fcef9074b)
2025-03-21 15:09:24 -07:00
Frank Praznik d37a3e2a71 x11: Fix backwards _NET_WM_SYNC_REQUEST init check
(cherry picked from commit b493e29a81)
2025-03-21 15:34:26 -04:00
Sam Lantinga ed8e7e85f0 SDL_ClaimWindowForGPUDevice() should fail for transparent windows
The GPU API doesn't currently support transparent windows (transparent swapchain effects doesn't seem possible on D3D12) so we should explicitly fail so users don't expect transparency and then not get it.

Fixes https://github.com/libsdl-org/SDL/issues/12410

(cherry picked from commit 2fbb583290)
2025-03-21 12:15:09 -07:00
Frank Praznik eb9faad124 cocoa: Fix zoom check when leaving fullscreen
Non-resizable windows will always report as zoomed, so isZoomed is not a reliable check here.

(cherry picked from commit 79081a178f)
2025-03-21 14:44:53 -04:00
Frank Praznik 3ed80843fe video: Fix boolean logic for getting the pending window position
(cherry picked from commit 03cdd297e0)
2025-03-21 11:36:46 -07:00
hwsmm 4029521a63 Don't send text event while ctrl/alt is held on X11/Wayland
(cherry picked from commit ac5b2b6102)
2025-03-20 21:27:22 -07:00
Sam Lantinga f971a59746 Fixed DebugLogRenderCommands() output
(cherry picked from commit 758eb256b9)
2025-03-20 21:25:23 -07:00
Sam Lantinga 5836266bfb We need to rebind D3D12 resources after updating them
Fixes https://github.com/libsdl-org/SDL/issues/12544

(cherry picked from commit 4ceb02434b)
2025-03-20 20:22:33 -07:00
Max ed893bde04 Updates SDL_SetEventFilter code snippet to SDL3
SDL_EventFilter points to a function that now returns a bool

(cherry picked from commit 817260c73d)
2025-03-20 16:50:53 -07:00
Carl Åstholm a934a36a18 emscripten: Don't use legacy JS library functions for assertions
(cherry picked from commit 54f5b73333)
2025-03-20 16:32:40 -07:00
Sam Lantinga 59857acd08 Always show the on-screen keyboard on Steam Deck
Steam will eventually have smarts about whether a keyboard is active and will igore the request appropriately.

Fixes https://github.com/libsdl-org/SDL/issues/12595

(cherry picked from commit 03a53ce0d1)
2025-03-20 16:30:04 -07:00
Sam Lantinga 8129b637f3 A Steam Controller might be generating keyboard input
We can't use keyboard input as a signal about whether a keyboard is attached. There might be keyboard input from any number of generated inputs or non-keyboard devices.

(cherry picked from commit 8caeaaacdd)
2025-03-20 16:30:04 -07:00
Sam Lantinga 9e1675671d Show the on-screen keyboard if we don't have active keyboard input
Active keyboard input is based on the input the user has most recently sent.

Fixes https://github.com/libsdl-org/SDL/issues/12595

(cherry picked from commit cbb83be895)
2025-03-20 16:30:04 -07:00
SDL Wiki Bot d39d951f89 Sync SDL3 wiki -> header
[ci skip]

(cherry picked from commit 67b4c3a156)
2025-03-20 16:30:04 -07:00
Ryan C. Gordon 10ed6f49a9 asyncio: SDL_LoadFileAsync was not null-terminating the file data.
(cherry picked from commit 10072bb07d)
2025-03-20 16:30:04 -07:00
Ryan C. Gordon c2c848a752 SDL_audio.h: Fixed typos in docs.
(cherry picked from commit 85435d5a14)
2025-03-20 16:30:04 -07:00
Sam Lantinga 8b191c3ca6 Fixed typo in build.gradle
(cherry picked from commit fe024b8fe3)
2025-03-20 11:22:20 -07:00
Sam Lantinga 06a412cd68 Fixed gradle deprecation warnings
"Space-assignment syntax in Groovy DSL has been deprecated. This is scheduled to be removed in Gradle 10.0"

(cherry picked from commit bf7b9b020e)
2025-03-20 11:05:56 -07:00
Sam Lantinga b74609d5f3 Use the android-21 SDK as documented in README-android.md
(cherry picked from commit ac28702504)
2025-03-20 11:05:56 -07:00
Sam Lantinga d8756582f9 Don't create surfaces with invalid pixel formats
Fixes https://github.com/libsdl-org/SDL/issues/12556

(cherry picked from commit 476e7e54cb)
2025-03-20 09:43:40 -07:00
Sam Lantinga ff90984dc3 Fix illegal calls to DwmGetWindowAttribute()
DWMWA_WINDOW_CORNER_PREFERENCE and DWMWA_BORDER_COLOR are only supported for DwmSetWindowAttribute(), they can't be queried.

Fixes https://github.com/libsdl-org/SDL/issues/12206
Closes https://github.com/libsdl-org/SDL/pull/12209

(cherry picked from commit f2ed5c7a1b)
2025-03-19 22:03:18 -07:00
Sam Lantinga 81952f9f96 Windows allows windows to be resized to zero height.
Changed the window client rect validation to take this into account.

Fixes https://github.com/libsdl-org/SDL/issues/9796

(cherry picked from commit 96bf12444c)
2025-03-19 21:23:06 -07:00
Sam Lantinga d0122ff624 Make sure we're getting called for the correct window
Fixes https://github.com/libsdl-org/SDL/issues/12525

(cherry picked from commit 47b0c75470)
2025-03-19 20:22:52 -07:00
Sam Lantinga 7a36aa37aa Fixed crash if a window couldn't be created on Windows
Fixes https://github.com/libsdl-org/SDL/issues/11482

(cherry picked from commit 3415bc920a)
2025-03-19 20:10:49 -07:00
Dragon-Baroque 464cb0ab6e The posix4 library has been merged into the libc library
(cherry picked from commit 07e4dea693)
2025-03-19 18:41:51 -07:00
Evan Hemsley ac21e3ef3f GPU Vulkan: Fix render pass race (#12587)
(cherry picked from commit c696e93180)
2025-03-19 13:34:26 -07:00
Frank Praznik a5b51669fb time: Fix compilation on Solaris
The tm_gmtoff field of the broken-down time 'tm' struct wasn't formally standardized until POSIX.1-2024, but practically it has been available on desktop *nix platforms such as Linux/glibc, FreeBSD, OpenBSD, NetBSD, OSX/macOS (NextStep before that), and others since the 1990s. The notable exception is SunOS/Solaris, where the timezone offset must still be retrieved in the strictly POSIX.1-2008 compliant way.

(cherry picked from commit 7b93a744c8)
2025-03-19 12:27:39 -04:00
Carl Åstholm 0ac030549b emscripten: Fix undefined behavior in opengles2 renderer
(cherry picked from commit 14deef997c)
2025-03-18 19:19:01 -07:00
Frank Praznik 6f1afe7084 video: Send pending coordinates for moved, hidden windows
Some backends can't actually position a window until it is shown/mapped, so assume that it will be where it was asked to be as long as it is hidden.

(cherry picked from commit d66483dfcc)
2025-03-18 19:56:25 -04:00
Sam Lantinga 6302589829 Use an autoreleasepool in Cocoa_GetDisplayUsableBounds()
Fixes https://github.com/libsdl-org/SDL/issues/12571

(cherry picked from commit 8b924df48b)
2025-03-18 14:40:01 -07:00
Sam Lantinga 3225d31679 Fixed building with SDL_LEAN_AND_MEAN
Fixes https://github.com/libsdl-org/SDL/issues/12578

(cherry picked from commit 82335fd0e9)
2025-03-18 09:55:46 -07:00
Arnoldo Adonaí Barón Robles ae05ab280d Fix Vulkan error check
(cherry picked from commit a551c2a6d7)
2025-03-17 22:11:21 -07:00
Caleb Cornett 51a6cb2cf5 gpu: Fix MTLLibrary dispatch data destructor
(cherry picked from commit 6d0fb0a2e6)
2025-03-17 18:54:30 -07:00
Evan Hemsley daf468e141 GPU: Fix Vulkan backend never checking deallocations (#12567)
---------

Co-authored-by: Sam Lantinga <slouken@libsdl.org>
(cherry picked from commit 0bd70684b3)
2025-03-17 13:59:47 -07:00
Sam Lantinga cd673c8254 Fixed raw input device GUIDs changing randomly between runs
On Windows 11, apparently HidD_GetManufacturerString() and HidD_GetProductString() can return TRUE without actually filling in any string data.

Fixes https://github.com/libsdl-org/SDL/issues/12566

(cherry picked from commit 4fc9509ab7)
2025-03-17 13:57:15 -07:00
Sam Lantinga 3f13c0b36d Fixed crash if info->path is NULL
(cherry picked from commit 715301cef5)
2025-03-17 09:46:57 -07:00
Cameron Gutman 3e34720851 mouse: Allow use of integer coordinates with fractional wheel events
SDL 2.0.18 added preciseX/Y to mouse wheel events, which we cannot
emulate in sdl2-compat without a mechanism to control integer position
and scroll deltas separately.

(cherry picked from commit aad1e35162)
2025-03-15 13:44:19 -07:00
Sam Lantinga 0799237d74 Added unaligned version of SDL_ConvertPixels_SwapNV_std()
Fixes https://github.com/libsdl-org/SDL/issues/12546

(cherry picked from commit 501e71f25f)
2025-03-15 09:25:39 -07:00
Sam Lantinga 53f64e40c4 Fixed SDL_GPUTextureSupportsSampleCount() documentation
Fixes https://github.com/libsdl-org/sdlwiki/issues/751

(cherry picked from commit ffe69fc354)
2025-03-14 09:30:44 -07:00
Frank Praznik a530df20b2 cocoa: Set the internal window data before calling methods that may result in referencing the internal data
(cherry picked from commit 512d97eaba)
2025-03-12 17:09:37 -04:00
Sam Lantinga b958189c92 Removed help for obsolete (and removed) command line option
(cherry picked from commit 50a397bb45)
2025-03-12 12:38:52 -07:00
Sam Lantinga 341f910835 Initialize the padding of aligned allocations to zero
Fixes valgrind uninitialized memory errors when doing SIMD blits
e.g. testautomation --filter surface_testScale

(cherry picked from commit 3235a4eb4f)
2025-03-12 11:43:09 -07:00
Joshua T. Fisher 84dff407d4 Fixup the mingw readme cmakelists
(cherry picked from commit 7746a9656e)
2025-03-11 19:43:43 -07:00
Sam Lantinga 21e6c5814c Fixed Nintendo controller face button layout under Steam
(cherry picked from commit 2ce3dfdf1d)
2025-03-10 17:31:12 -07:00
Sam Lantinga 776f0a685c Fixed sscanf("026", "%1x%1x%1x", &r, &g, &b)
Fixes https://github.com/libsdl-org/SDL/issues/12510

(cherry picked from commit be6ed6e9c4)
2025-03-10 14:46:30 -07:00
Sam Lantinga 9f32fafe21 Use sized types when fixing undefined behavior
(cherry picked from commit 24339524c5)
2025-03-10 09:54:05 -07:00
rohlem 74b3b8e9e3 avoid UB (left shift of negative number) in SDL_windowsevents.c
(cherry picked from commit f1d16e9b4d)
2025-03-10 09:54:05 -07:00
Frank Praznik fa4a9ba74e wayland: Fix enum/boolean comparison and assignment
(cherry picked from commit f2866418d4)
2025-03-09 12:28:39 -04:00
Cameron Gutman 9a6f8a2512 mouse: Add internal integer mouse mode hint for sdl2-compat
Performing this inside SDL3 dramatically simplifies sdl2-compat. See https://github.com/libsdl-org/sdl2-compat/issues/372.

(cherry picked from commit 597bfe6b27)
2025-03-08 19:07:05 -08:00
bobsayshilol 1173bc2dde emscripten: Fix handling of special HTML targets
With ASAN enabled the existing code triggered null-pointer-dereference
in the strcmp since EMSCRIPTEN_EVENT_TARGET_WINDOW is a "fake" pointer
with the value ((const char*)2). In fixing this it was also noticed
that using the #window/#document/#screen targets as mentioned in the
docs fails since document.querySelector() returns null for them and we
should instead be mapping them to the special HTML targets provided.

(cherry picked from commit 65cd2256c5)
2025-03-08 17:16:57 -08:00
TheMode ada55bd887 Implement SDL_GetSystemRAM and SDL_GetNumLogicalCPUCores for the 3ds (#12494)
(cherry picked from commit 5d804a39d9)
2025-03-08 09:54:43 -08:00
Sam Lantinga fe97cff7d1 Fixed memory leak in memory leak tracking
(cherry picked from commit 99336ea378)
2025-03-08 09:54:43 -08:00
ds-sloth 8cdeb1a35a Fix n3ds/SDL_syssem.c:SDL_SignalSemaphore (libsdl-org/SDL#12411)
(cherry picked from commit 0306b5a865)
2025-03-07 17:32:05 -08:00
Sam Lantinga 7c82171a85 Fixed pen events on iOS after reinitializing SDL
We weren't resetting apple_pencil_id, so not re-registering it later.

(cherry picked from commit 3353b92a96)
2025-03-07 16:33:09 -08:00
Sam Lantinga 2d2085c80b Add a link to docs/INTRO-mingw.md
(cherry picked from commit d631a3add0)
2025-03-06 16:26:15 -08:00
Joshua T. Fisher 03a4eea0ef Added MinGW Intro readme, touched up CMake and Visual Studio readmes. (#12485)
(cherry picked from commit 04b4577b58)
2025-03-06 16:26:15 -08:00
Sam Lantinga fec3e2cd45 Removed logic forcing vsync on if setting it off fails
The platforms that needed this (Windows Phone and Windows RT) are no longer supported, and if this is needed in the future it should be done at the renderer level, not here.

Fixes https://github.com/libsdl-org/SDL/issues/12475

(cherry picked from commit b99ff00a95)
2025-03-06 16:18:42 -08:00
Sam Lantinga 2aec1c2ef6 Added support for SDL_PIXELFORMAT_MJPG to SDL_DuplicateSurface()
Fixes https://github.com/libsdl-org/SDL/issues/12472

(cherry picked from commit 4c82b5843e)
2025-03-05 23:39:33 -08:00
Sam Lantinga b32cd4f84b Make texture scale mode a part of the 2D renderer draw state
Also added texture addressing mode support to the PSP and Vita renderers (untested)

Fixes https://github.com/libsdl-org/SDL/issues/12461

(cherry picked from commit cb099ebd4f)
2025-03-05 22:39:31 -08:00
SDL Wiki Bot 550bdc658a Sync SDL3 wiki -> header
[ci skip]

(cherry picked from commit f01bcaeb17)
2025-03-05 09:13:10 -08:00
Sam Lantinga d75ba9c2d2 Added SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT
(cherry picked from commit fe9bdcf508)
2025-03-05 09:13:10 -08:00
SDL Wiki Bot 2477f7f982 Sync SDL3 wiki -> header
[ci skip]

(cherry picked from commit 9f557941f3)
2025-03-05 07:26:50 -08:00
Sam Lantinga e454d7d4be Document the thread safety of SDL surface functions
(cherry picked from commit 8f40dad460)
2025-03-05 07:26:49 -08:00
Sam Lantinga cd8bffb2dd Fixed continuous logging if returning to desktop mode fails on X11
(cherry picked from commit aef240b2e4)
2025-03-04 17:26:03 -08:00
Sam Lantinga 9646e3cc1b Handle XWayland not sending display disconnected events
Also updated X11_CheckDisplaysMoved() to handle multiple X11 screens

Fixes https://github.com/libsdl-org/SDL/issues/12462

(cherry picked from commit e9632c83c7)
2025-03-04 17:26:03 -08:00
Sam Lantinga 1a2362ebf1 Updated to version 3.2.9 for development 2025-03-04 15:07:23 -08:00
135 changed files with 3379 additions and 1339 deletions

No files matched your search

+6 -5
View File
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
endif()
# See docs/release_checklist.md
project(SDL3 LANGUAGES C VERSION "3.2.8")
project(SDL3 LANGUAGES C VERSION "3.2.14")
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(SDL3_MAINPROJECT ON)
@@ -1291,8 +1291,8 @@ if(ANDROID)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/android")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/android/*.c")
sdl_sources("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_property(SOURCE "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement")
sdl_sources("${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_property(SOURCE "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/android/*.c")
set(HAVE_SDL_MISC TRUE)
@@ -2188,6 +2188,7 @@ elseif(APPLE)
set(SDL_CAMERA_DRIVER_COREMEDIA 1)
set(HAVE_CAMERA TRUE)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/coremedia/*.m")
set(SDL_FRAMEWORK_AVFOUNDATION 1)
endif()
endif()
@@ -3016,7 +3017,7 @@ if(SDL_GPU)
set(SDL_GPU_D3D11 1)
set(HAVE_SDL_GPU TRUE)
endif()
if(SDL_RENDER_D3D12)
if(WINDOWS)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d12/*.c")
set(SDL_GPU_D3D12 1)
set(HAVE_SDL_GPU TRUE)
@@ -3287,7 +3288,7 @@ else()
endif()
if(ANDROID)
sdl_include_directories(PRIVATE SYSTEM "${ANDROID_NDK}/sources/android/cpufeatures")
sdl_include_directories(PRIVATE SYSTEM "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures")
endif()
if(APPLE)
+1
View File
@@ -3,6 +3,7 @@
SDL supports a number of development environments:
- [CMake](docs/INTRO-cmake.md)
- [Visual Studio on Windows](docs/INTRO-visualstudio.md)
- [gcc on Windows](docs/INTRO-mingw.md)
- [Xcode on Apple platforms](docs/INTRO-xcode.md)
- [Android Studio](docs/INTRO-androidstudio.md)
- [Emscripten for web](docs/INTRO-emscripten.md)
+2 -2
View File
@@ -168,8 +168,8 @@
</Link>
<PreBuildEvent>
<Command>
call $(ProjectDir)..\..\src\render\direct3d12\compile_shaders_xbox.bat $(ProjectDir)..\
call $(ProjectDir)..\..\src\gpu\d3d12\compile_shaders_xbox.bat $(ProjectDir)..\
call "$(ProjectDir)..\..\src\render\direct3d12\compile_shaders_xbox.bat" "$(ProjectDir)..\"
call "$(ProjectDir)..\..\src\gpu\d3d12\compile_shaders_xbox.bat" "$(ProjectDir)..\"
</Command>
</PreBuildEvent>
<PreBuildEvent>
+10
View File
@@ -1,6 +1,16 @@
This is a list of major changes in SDL's version history.
---------------------------------------------------------------------------
3.2.10:
---------------------------------------------------------------------------
* Added SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT to control whether XSelectInput() should be called on external windows to enable input events.
---------------------------------------------------------------------------
3.2.4:
---------------------------------------------------------------------------
* Added SDL_StretchSurface()
---------------------------------------------------------------------------
3.2.0:
---------------------------------------------------------------------------
+2 -2
View File
@@ -19,10 +19,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.2.8</string>
<string>3.2.14</string>
<key>CFBundleSignature</key>
<string>SDLX</string>
<key>CFBundleVersion</key>
<string>3.2.8</string>
<string>3.2.14</string>
</dict>
</plist>
+4 -4
View File
@@ -3086,7 +3086,7 @@
CLANG_ENABLE_OBJC_ARC = YES;
DEPLOYMENT_POSTPROCESSING = YES;
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
DYLIB_CURRENT_VERSION = 201.8.0;
DYLIB_CURRENT_VERSION = 201.14.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
@@ -3121,7 +3121,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.2.8;
MARKETING_VERSION = 3.2.14;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
PRODUCT_NAME = SDL3;
@@ -3150,7 +3150,7 @@
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
DYLIB_CURRENT_VERSION = 201.8.0;
DYLIB_CURRENT_VERSION = 201.14.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -3182,7 +3182,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.2.8;
MARKETING_VERSION = 3.2.14;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
+1 -1
View File
@@ -1,4 +1,4 @@
Title SDL 3.2.8
Title SDL 3.2.14
Version 1
Description SDL Library for macOS (http://www.libsdl.org)
DefaultLocation /Library/Frameworks
+4 -4
View File
@@ -5,7 +5,7 @@ plugins {
def buildWithCMake = project.hasProperty('BUILD_WITH_CMAKE');
android {
namespace "org.libsdl.app"
namespace = "org.libsdl.app"
compileSdkVersion 35
defaultConfig {
minSdkVersion 21
@@ -14,12 +14,12 @@ android {
versionName "1.0"
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-19"
arguments "APP_PLATFORM=android-21"
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
abiFilters 'arm64-v8a'
}
cmake {
arguments "-DANDROID_PLATFORM=android-19", "-DANDROID_STL=c++_static"
arguments "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_static"
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
abiFilters 'arm64-v8a'
}
@@ -53,7 +53,7 @@ android {
}
lint {
abortOnError false
abortOnError = false
}
}
@@ -60,7 +60,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 2;
private static final int SDL_MICRO_VERSION = 8;
private static final int SDL_MICRO_VERSION = 14;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
+63 -15
View File
@@ -424,7 +424,11 @@ sub dewikify_chunk {
$str .= "\n```$codelang\n$code\n```\n";
}
} elsif ($dewikify_mode eq 'manpage') {
$str =~ s/\./\\[char46]/gms; # make sure these can't become control codes.
# make sure these can't become part of roff syntax.
$str =~ s/\./\\[char46]/gms;
$str =~ s/"/\\(dq/gms;
$str =~ s/'/\\(aq/gms;
if ($wikitype eq 'mediawiki') {
# Dump obvious wikilinks.
if (defined $apiprefixregex) {
@@ -449,33 +453,52 @@ sub dewikify_chunk {
# bullets
$str =~ s/^\* /\n\\\(bu /gm;
} elsif ($wikitype eq 'md') {
# bullets
$str =~ s/^\- /\n\\(bu /gm;
# merge paragraphs
$str =~ s/^[ \t]+//gm;
$str =~ s/([^\-\n])\n([^\-\n])/$1 $2/g;
$str =~ s/\n\n/\n.PP\n/g;
# Dump obvious wikilinks.
if (defined $apiprefixregex) {
$str =~ s/\[(\`?$apiprefixregex[a-zA-Z0-9_]+\`?)\]\($apiprefixregex[a-zA-Z0-9_]+\)/\n.BR $1\n/gms;
my $apr = $apiprefixregex;
if(!($apr =~ /\A\(.*\)\Z/s)) {
# we're relying on the apiprefixregex having a capturing group.
$apr = "(" . $apr . ")";
}
$str =~ s/(\S*?)\[\`?($apr[a-zA-Z0-9_]+)\`?\]\($apr[a-zA-Z0-9_]+\)(\S*)\s*/\n.BR "" "$1" "$2" "$5"\n/gm;
# handle cases like "[x](x), [y](y), [z](z)" being separated.
while($str =~ s/(\.BR[^\n]*)\n\n\.BR/$1\n.BR/gm) {}
}
# links
$str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\n.URL "$2" "$1"\n/g;
# <code></code> is also popular. :/
$str =~ s/\s*\`(.*?)\`\s*/\n.BR $1\n/gms;
$str =~ s/\s*(\S*?)\`([^\n]*?)\`(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms;
# bold+italic (this looks bad, just make it bold).
$str =~ s/\s*\*\*\*(.*?)\*\*\*\s*/\n.B $1\n/gms;
$str =~ s/\s*(\S*?)\*\*\*([^\n]*?)\*\*\*(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms;
# bold
$str =~ s/\s*\*\*(.*?)\*\*\s*/\n.B $1\n/gms;
$str =~ s/\s*(\S*?)\*\*([^\n]*?)\*\*(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms;
# italic
$str =~ s/\s*\*(.*?)\*\s*/\n.I $1\n/gms;
# bullets
$str =~ s/^\- /\n\\\(bu /gm;
$str =~ s/\s*(\S*?)\*([^\n]*?)\*(\S*)\s*/\n.IR "" "$1" "$2" "$3"\n/gms;
}
# cleanup unnecessary quotes
$str =~ s/(\.[IB]R?)(.*?) ""\n/$1$2\n/gm;
$str =~ s/(\.[IB]R?) "" ""(.*?)\n/$1$2\n/gm;
$str =~ s/"(\S+)"/$1/gm;
# cleanup unnecessary whitespace
$str =~ s/ +\n/\n/gm;
if (defined $code) {
$code =~ s/\A\n+//gms;
$code =~ s/\n+\Z//gms;
$code =~ s/\\/\\(rs/gms;
if ($dewikify_manpage_code_indent) {
$str .= "\n.IP\n"
} else {
@@ -580,7 +603,7 @@ sub dewikify {
$retval .= dewikify_chunk($wikitype, $1, $2, $3);
}
} elsif ($wikitype eq 'md') {
while ($str =~ s/\A(.*?)\n```(.*?)\n(.*?)\n```\n//ms) {
while ($str =~ s/\A(.*?)\n?```(.*?)\n(.*?)\n```\n//ms) {
$retval .= dewikify_chunk($wikitype, $1, $2, $3);
}
}
@@ -2765,7 +2788,6 @@ __EOF__
my $wikitype = $wikitypes{$sym};
my $sectionsref = $wikisyms{$sym};
my $remarks = $sectionsref->{'Remarks'};
my $params = $sectionsref->{'Function Parameters'};
my $returns = $sectionsref->{'Return Value'};
my $version = $sectionsref->{'Version'};
my $threadsafety = $sectionsref->{'Thread Safety'};
@@ -2773,6 +2795,23 @@ __EOF__
my $examples = $sectionsref->{'Code Examples'};
my $deprecated = $sectionsref->{'Deprecated'};
my $headerfile = $manpageheaderfiletext;
my $params = undef;
if ($symtype == -1) { # category documentation block.
# nothing to be done here.
} elsif (($symtype == 1) || (($symtype == 5))) { # we'll assume a typedef (5) with a \param is a function pointer typedef.
$params = $sectionsref->{'Function Parameters'};
} elsif ($symtype == 2) {
$params = $sectionsref->{'Macro Parameters'};
} elsif ($symtype == 3) {
$params = $sectionsref->{'Fields'};
} elsif ($symtype == 4) {
$params = $sectionsref->{'Values'};
} else {
die("Unexpected symtype $symtype");
}
$headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g;
$headerfile .= "\n";
@@ -2839,18 +2878,22 @@ __EOF__
$str .= dewikify($wikitype, $deprecated) . "\n";
}
my $incfile = $mainincludefname;
if (defined $headerfile) {
$str .= ".SH HEADER FILE\n";
$str .= dewikify($wikitype, $headerfile) . "\n";
if($headerfile =~ /Defined in (.*)/) {
$incfile = $1;
}
}
$str .= ".SH SYNOPSIS\n";
$str .= ".nf\n";
$str .= ".B #include \\(dq$mainincludefname\\(dq\n";
$str .= ".B #include <$incfile>\n";
$str .= ".PP\n";
my @decllines = split /\n/, $decl;
foreach (@decllines) {
$_ =~ s/\\/\\(rs/g; # fix multiline macro defs
$_ =~ s/"/\\(dq/g;
$str .= ".BI \"$_\n";
}
$str .= ".fi\n";
@@ -2938,8 +2981,11 @@ __EOF__
}
if (defined $returns) {
# Chop datatype in parentheses off the front.
if(!($returns =~ s/\A\([^\[]*\[[^\]]*\]\([^\)]*\)[^\)]*\) //ms)) {
$returns =~ s/\A\([^\)]*\) //ms;
}
$returns = dewikify($wikitype, $returns);
$returns =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front.
$str .= ".SH RETURN VALUE\n";
$str .= "$returns\n";
}
@@ -2975,6 +3021,8 @@ __EOF__
s/\A\/*//;
s/\A\.BR\s+//; # dewikify added this, but we want to handle it.
s/\A\.I\s+//; # dewikify added this, but we want to handle it.
s/\A\.PP\s*//; # dewikify added this, but we want to handle it.
s/\\\(bu//; # dewikify added this, but we want to handle it.
s/\A\s*[\:\*\-]\s*//;
s/\A\s+//;
s/\s+\Z//;
+1 -1
View File
@@ -823,7 +823,7 @@ macro(CheckPTHREAD)
if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
set(PTHREAD_LDFLAGS "-mt -lpthread")
else()
set(PTHREAD_LDFLAGS "-pthread -lposix4")
set(PTHREAD_LDFLAGS "-pthread")
endif()
elseif(SYSV5)
set(PTHREAD_CFLAGS "-D_REENTRANT -Kthread")
+16 -9
View File
@@ -5,7 +5,12 @@ The easiest way to use SDL is to include it as a subproject in your project.
We'll start by creating a simple project to build and run [hello.c](hello.c)
Create the file CMakeLists.txt
# Get a copy of the SDL source:
```sh
git clone https://github.com/libsdl-org/SDL.git vendored/SDL
```
# Create the file CMakeLists.txt
```cmake
cmake_minimum_required(VERSION 3.16)
project(hello)
@@ -25,24 +30,26 @@ add_executable(hello WIN32 hello.c)
target_link_libraries(hello PRIVATE SDL3::SDL3)
```
Build:
# Configure and Build:
```sh
cmake -S . -B build
cmake --build build
```
Run:
- On Windows the executable is in the build Debug directory:
```sh
cd build/Debug
./hello
```
- On other platforms the executable is in the build directory:
# Run:
The executable should be in the `build` directory:
```sh
cd build
./hello
```
If there wasn't an executable there despite the above Build section running successfully, it's likely because you're following this guide using the Visual Studio toolchain, it should instead be in the `build/Debug` directory:
```sh
cd build/Debug
./hello
```
A more complete example is available at:
https://github.com/Ravbug/sdl3-sample
+95
View File
@@ -0,0 +1,95 @@
# Introduction to SDL with MinGW
Without getting deep into the history, MinGW is a long running project that aims to bring gcc to Windows. That said, there's many distributions, versions, and forks floating around. We recommend installing [MSYS2](https://www.msys2.org/), as it's the easiest way to get a modern toolchain with a package manager to help with dependency management. This would allow you to follow the MSYS2 section below.
Otherwise you'll want to follow the "Other Distributions" section below.
We'll start by creating a simple project to build and run [hello.c](hello.c).
# MSYS2
Open the `MSYS2 UCRT64` prompt and then ensure you've installed the following packages. This will get you working toolchain, CMake, Ninja, and of course SDL3.
```sh
pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-sdl3
```
## Create the file CMakeLists.txt
```cmake
cmake_minimum_required(VERSION 3.26)
project(hello C CXX)
find_package(SDL3 REQUIRED)
add_executable(hello)
target_sources(hello
PRIVATE
hello.c
)
target_link_libraries(hello SDL3::SDL3)
```
## Configure and Build:
```sh
cmake -S . -B build
cmake --build build
```
## Run:
The executable is in the `build` directory:
```sh
cd build
./hello
```
# Other Distributions
Things can get quite complicated with other distributions of MinGW. If you can't follow [the cmake intro](INTRO-cmake.md), perhaps due to issues getting cmake to understand your toolchain, this section should work.
## Acquire SDL
Download the `SDL3-devel-<version>-mingw.zip` asset from [the latest release.](https://github.com/libsdl-org/SDL/releases/latest) Then extract it inside your project folder such that the output of `ls SDL3-<version>` looks like `INSTALL.md LICENSE.txt Makefile README.md cmake i686-w64-mingw32 x86_64-w64-mingw32`.
## Know your Target Architecture
It is not uncommon for folks to not realize their distribution is targeting 32bit Windows despite things like the name of the toolchain, or the fact that they're running on a 64bit system. We'll ensure we know up front what we need:
Create a file named `arch.c` with the following contents:
```c
#include <stddef.h>
#include <stdio.h>
int main() {
#if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
size_t ptr_size = sizeof(int*);
if (4 == ptr_size) puts("i686-w64-mingw32");
else if (8 == ptr_size) puts("x86_64-w64-mingw32");
else puts("Unknown Architecture");
#else
puts("Unknown Architecture");
#endif
return 0;
}
```
Then run
```sh
gcc arch.c
./a.exe
```
This should print out which library directory we'll need to use when compiling, keep this value in mind, you'll need to use it when compiling in the next section as `<arch>`. If you get "Unknown Architecture" please [report a bug](https://github.com/libsdl-org/SDL/issues).
## Build and Run
Now we should have everything needed to compile and run our program. You'll need to ensure to replace `<version>` with the version of the release of SDL3 you downloaded, as well as use the `<arch>` we learned in the previous section.
```sh
gcc hello.c -o hello.exe -I SDL3-<version>/<arch>/include -L SDL3-<version>/<arch>/lib -lSDL3 -mwindows
cp SDL3-<version>/<arch>/bin/SDL3.dll SDL3.dll
./hello.exe
```
+5 -3
View File
@@ -5,10 +5,12 @@ The easiest way to use SDL is to include it as a subproject in your project.
We'll start by creating a simple project to build and run [hello.c](hello.c)
- Get a copy of the SDL source, you can clone the repo, or download the "Source Code" asset from [the latest release.](https://github.com/libsdl-org/SDL/releases/latest)
- If you've downloaded a release, make sure to extract the contents somewhere you can find it.
- Create a new project in Visual Studio, using the C++ Empty Project template
- Add hello.c to the Source Files
- Right click the solution, select add an existing project, navigate to VisualC/SDL and add SDL.vcxproj
- Select your main project and go to Project -> Add Reference and select SDL3
- Select your main project and go to Project -> Properties, set the filter at the top to "All Configurations" and "All Platforms", select VC++ Directories and add the SDL include directory to "Include Directories"
- Right click the solution, select add an existing project, navigate to `VisualC/SDL` from within the source you cloned or downloaded above and add SDL.vcxproj
- Select your main project and go to Project -> Add -> Reference and select SDL3
- Select your main project and go to Project -> Properties, set the filter at the top to "All Configurations" and "All Platforms", select C/C++ -> General and add the SDL include directory to "Additional Include Directories"
- Build and run!
+8 -8
View File
@@ -242,7 +242,7 @@ not give you any processing time after the events are delivered.
e.g.
int HandleAppEvents(void *userdata, SDL_Event *event)
bool HandleAppEvents(void *userdata, SDL_Event *event)
{
switch (event->type)
{
@@ -250,12 +250,12 @@ e.g.
/* Terminate the app.
Shut everything down before returning from this function.
*/
return 0;
return false;
case SDL_EVENT_LOW_MEMORY:
/* You will get this when your app is paused and iOS wants more memory.
Release as much memory as possible.
*/
return 0;
return false;
case SDL_EVENT_WILL_ENTER_BACKGROUND:
/* Prepare your app to go into the background. Stop loops, etc.
This gets called when the user hits the home button, or gets a call.
@@ -264,15 +264,15 @@ e.g.
in addition, you should set the render target to NULL, if you're using
it, e.g. call SDL_SetRenderTarget(renderer, NULL).
*/
return 0;
return false;
case SDL_EVENT_DID_ENTER_BACKGROUND:
/* Your app is NOT active at this point. */
return 0;
return false;
case SDL_EVENT_WILL_ENTER_FOREGROUND:
/* This call happens when your app is coming back to the foreground.
Restore all your state here.
*/
return 0;
return false;
case SDL_EVENT_DID_ENTER_FOREGROUND:
/* Restart your loops here.
Your app is interactive and getting CPU again.
@@ -283,10 +283,10 @@ e.g.
event SDL_EVENT_RENDER_DEVICE_RESET and recreate your OpenGL context and
restore your textures when you get it, or quit the app.
*/
return 0;
return false;
default:
/* No special processing, add it to the event queue */
return 1;
return true;
}
}
+30 -26
View File
@@ -1,32 +1,6 @@
SDL 3.0 has new support for high DPI displays. Interfaces provided by SDL uses the platform's native coordinates unless otherwise specified.
To reconcile platform differences in their approach to high-density scaling, SDL provides the following interfaces:
- `SDL_GetWindowSize()` retrieves the window dimensions in native coordinates.
- `SDL_GetWindowSizeInPixels()` retrieves the window dimensions in pixels-addressable.
- `SDL_GetDisplayContentScale()` retrieves the suggested amplification factor when drawing in native coordinates.
- `SDL_GetWindowDisplayScale()` retrieves the suggested amplification factor when drawing in pixels-addressable.
- `SDL_GetWindowPixelDensity()` retrieves how many addressable pixels correspond to one unit of native coordinates.
- `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` is emitted when the value retrievable from `SDL_GetWindowSizeInPixels()` changes.
- `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` is emitted when the value retrievable from `SDL_GetWindowDisplayScale()` changes.
- Windows created with `SDL_WINDOW_HIGH_PIXEL_DENSITY` will ask the platform to display addressable pixels at their natural scale.
## Numeric example
Given a fullscreen window spanning a 3840x2160 monitor set to 2x display or 200% scaling, the following tabulates the effect of creating a window with or without `SDL_WINDOW_HIGH_PIXEL_DENSITY` on MacOS and Win32:
| Value | MacOS (Default) | MacOS (HD) | Win32 (Default & HD) |
|--------------------------------|-----------------|------------|----------------------|
| `SDL_GetWindowSize()` | 1920x1080 | 1920x1080 | 3840x2160 |
| `SDL_GetWindowSizeInPixels()` | 1920x1080 | 3840x2160 | 3840x2160 |
| `SDL_GetDisplayContentScale()` | 1.0 | 1.0 | 2.0 |
| `SDL_GetWindowDisplayScale()` | 1.0 | 2.0 | 2.0 |
| `SDL_GetWindowPixelDensity()` | 1.0 | 2.0 | 1.0 |
Observe the philosophical difference between the approaches taken by MacOS and Win32:
- Win32 coordinate system always deals in physical device pixels, high DPI support is achieved by providing an advisory hint for the developer to enlarge drawn objects. Ignoring the advisory scale factor results in graphics appearing tiny.
- MacOS coordinate system always deals in physical content sizes, high DPI support is achieved by providing an optional flag for the developer to request finer granularity. Omitting the granularity request results in graphics appearing coarse.
## Explanation
Displays now have a content display scale, which is the expected scale for content based on the DPI settings of the display. For example, a 4K display might have a 2.0 (200%) display scale, which means that the user expects UI elements to be twice as big on this display, to aid in readability. You can query the display content scale using `SDL_GetDisplayContentScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event.
@@ -34,3 +8,33 @@ Displays now have a content display scale, which is the expected scale for conte
The window size is now distinct from the window pixel size, and the ratio between the two is the window pixel density. If the window is created with the `SDL_WINDOW_HIGH_PIXEL_DENSITY` flag, SDL will try to match the native pixel density for the display, otherwise it will try to have the pixel size match the window size. You can query the window pixel density using `SDL_GetWindowPixelDensity()`. You can query the window pixel size using `SDL_GetWindowSizeInPixels()`, and when this changes you get an `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event. You are guaranteed to get a `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event when a window is created and resized, and you can use this event to create and resize your graphics context for the window.
The window has a display scale, which is the scale from the pixel resolution to the desired content size, e.g. the combination of the pixel density and the content scale. For example, a 3840x2160 window displayed at 200% on Windows, and a 1920x1080 window with the high density flag on a 2x display on macOS will both have a pixel size of 3840x2160 and a display scale of 2.0. You can query the window display scale using `SDL_GetWindowDisplayScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event.
## Numeric example
Given a window spanning a 3840x2160 monitor set to 2x display or 200% scaling, the following tabulates the effect of creating a window with or without `SDL_WINDOW_HIGH_PIXEL_DENSITY` on macOS and Windows:
| Value | macOS (Default) | macOS (HD) | Windows (Default & HD) |
|--------------------------------|-----------------|------------|------------------------|
| `SDL_GetWindowSize()` | 1920x1080 | 1920x1080 | 3840x2160 |
| `SDL_GetWindowSizeInPixels()` | 1920x1080 | 3840x2160 | 3840x2160 |
| `SDL_GetDisplayContentScale()` | 1.0 | 1.0 | 2.0 |
| `SDL_GetWindowDisplayScale()` | 1.0 | 2.0 | 2.0 |
| `SDL_GetWindowPixelDensity()` | 1.0 | 2.0 | 1.0 |
Observe the difference between the approaches taken by macOS and Windows:
- The Windows and Android coordinate system always deals in physical device pixels, high DPI support is achieved by providing a content scale that tells the developer to draw objects larger. Ignoring this scale factor results in graphics appearing tiny.
- The macOS and iOS coordinate system always deals in window coordinates, high DPI support is achieved by providing an optional flag for the developer to request more pixels. Omitting this flag results in graphics having low detail.
- On Linux, X11 uses a similar approach to Windows and Wayland uses a similar approach to macOS.
## Solution
Proper high DPI support takes into account both the content scale and the pixel density.
First, you'd create your window with the `SDL_WINDOW_HIGH_PIXEL_DENSITY` flag, assuming you want the highest detail possible. Then you'd get the window display scale to see how much your UI elements should be enlarged to be readable.
If you're using the SDL 2D renderer, SDL provides the function `SDL_ConvertEventToRenderCoordinates()` to convert mouse coordinates between window coordinates and rendering coordinates, and the more general functions `SDL_RenderCoordinatesFromWindow()` and `SDL_RenderCoordinatesToWindow()` to do other conversion between them.
If you're not using the 2D renderer, you can implement this yourself using `SDL_GetWindowPixelDensity()` as scale factor to convert from window coordinates to pixels.
Finally you'll want to test on both Windows and macOS if possible to make sure your high DPI support works in all environments.
+8 -8
View File
@@ -65,7 +65,7 @@ not give you any processing time after the events are delivered.
e.g.
int HandleAppEvents(void *userdata, SDL_Event *event)
bool HandleAppEvents(void *userdata, SDL_Event *event)
{
switch (event->type)
{
@@ -73,37 +73,37 @@ e.g.
/* Terminate the app.
Shut everything down before returning from this function.
*/
return 0;
return false;
case SDL_EVENT_LOW_MEMORY:
/* You will get this when your app is paused and iOS wants more memory.
Release as much memory as possible.
*/
return 0;
return false;
case SDL_EVENT_WILL_ENTER_BACKGROUND:
/* Prepare your app to go into the background. Stop loops, etc.
This gets called when the user hits the home button, or gets a call.
*/
return 0;
return false;
case SDL_EVENT_DID_ENTER_BACKGROUND:
/* This will get called if the user accepted whatever sent your app to the background.
If the user got a phone call and canceled it, you'll instead get an SDL_EVENT_DID_ENTER_FOREGROUND event and restart your loops.
When you get this, you have 5 seconds to save all your state or the app will be terminated.
Your app is NOT active at this point.
*/
return 0;
return false;
case SDL_EVENT_WILL_ENTER_FOREGROUND:
/* This call happens when your app is coming back to the foreground.
Restore all your state here.
*/
return 0;
return false;
case SDL_EVENT_DID_ENTER_FOREGROUND:
/* Restart your loops here.
Your app is interactive and getting CPU again.
*/
return 0;
return false;
default:
/* No special processing, add it to the event queue */
return 1;
return true;
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ cmake --install build
## Compiling a HelloWorld
[PSP Hello World](https://psp-dev.org/doku.php?id=tutorial:hello_world)
[PSP Hello World](https://pspdev.github.io/basic_programs.html#hello-world)
## To Do
- PSP Screen Keyboard
+28 -40
View File
@@ -1,60 +1,48 @@
# Versioning
## Since 2.23.0
## Since 3.2.0
SDL follows an "odd/even" versioning policy, similar to GLib, GTK, Flatpak
and older versions of the Linux kernel:
* The major version (first part) increases when backwards compatibility
is broken, which will happen infrequently.
* If the minor version (second part) is divisible by 2
(for example 2.24.x, 2.26.x), this indicates a version of SDL that
is believed to be stable and suitable for production use.
* If the minor version (second part) and the patch version (third part) is
divisible by 2 (for example 3.2.6, 3.4.0), this indicates a version of
SDL that is believed to be stable and suitable for production use.
* In stable releases, the patchlevel or micro version (third part)
indicates bugfix releases. Bugfix releases should not add or
remove ABI, so the ".0" release (for example 2.24.0) should be
forwards-compatible with all the bugfix releases from the
same cycle (for example 2.24.1).
indicates bugfix releases. Bugfix releases may add small changes
to the ABI, so newer patch versions are backwards-compatible but
not fully forwards-compatible. For example, programs built against
SDL 3.2.0 should work fine with SDL 3.2.8, but programs built against
SDL 3.2.8 may not work with 3.2.0.
* The minor version increases when new API or ABI is added, or when
other significant changes are made. Newer minor versions are
backwards-compatible, but not fully forwards-compatible.
For example, programs built against SDL 2.24.x should work fine
with SDL 2.26.x, but programs built against SDL 2.26.x will not
necessarily work with 2.24.x.
* The minor version increases when significant changes are made that
require longer development or testing time, e.g. major new functionality,
or revamping support for a platform. Newer minor versions are
backwards-compatible, but not fully forwards-compatible. For example,
programs built against SDL 3.2.x should work fine with SDL 3.4.x,
but programs built against SDL 3.4.x may not work with 3.2.x.
* If the minor version (second part) is not divisible by 2
(for example 2.23.x, 2.25.x), this indicates a development prerelease
of SDL that is not suitable for stable software distributions.
* If the minor version (second part) or patch version (third part) is not
divisible by 2 (for example 3.2.9, 3.3.x), this indicates a development
prerelease of SDL that is not suitable for stable software distributions.
Use with caution.
* The patchlevel or micro version (third part) increases with
each prerelease.
* Each prerelease might add new API and/or ABI.
* The patchlevel or micro version (third part) increases with each prerelease.
* Prereleases are backwards-compatible with older stable branches.
For example, 2.25.x will be backwards-compatible with 2.24.x.
For example, programs built against SDL 3.2.x should work fine with
SDL 3.3.x, but programs built against SDL 3.3.x may not work with 3.2.x.
* Prereleases are not guaranteed to be backwards-compatible with
each other. For example, new API or ABI added in 2.25.1
might be removed or changed in 2.25.2.
If this would be a problem for you, please do not use prereleases.
* Prereleases are not guaranteed to be backwards-compatible with each other.
For example, new API or ABI added in 3.3.0 might be removed or changed in
3.3.1. If this would be a problem for you, please do not use prereleases.
* Only upgrade to a prerelease if you can guarantee that you will
promptly upgrade to the stable release that follows it.
For example, do not upgrade to 2.23.x unless you will be able to
upgrade to 2.24.0 when it becomes available.
* Only use a prerelease if you can guarantee that you will promptly upgrade
to the stable release that follows it. For example, do not use 3.3.x
unless you will be able to upgrade to 3.4.0 when it becomes available.
* Software distributions that have a freeze policy (in particular Linux
distributions with a release cycle, such as Debian and Fedora)
should usually only package stable releases, and not prereleases.
should only package stable releases, and not prereleases.
## Before 2.23.0
Older versions of SDL followed a similar policy, but instead of the
odd/even rule applying to the minor version, it applied to the patchlevel
(micro version, third part). For example, 2.0.22 was a stable release
and 2.0.21 was a prerelease.
+4
View File
@@ -59,6 +59,10 @@ encounter limitations or behavior that is different from other windowing systems
`SDL_APP_ID` hint string, the desktop entry file name should match the application ID. For example, if your
application ID is set to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`.
### Keyboard grabs don't work when running under XWayland
- On GNOME based desktops, the dconf setting `org/gnome/mutter/wayland/xwayland-allow-grabs` must be enabled.
## Using custom Wayland windowing protocols with SDL windows
Under normal operation, an `SDL_Window` corresponds to an XDG toplevel window, which provides a standard desktop window.
+1 -1
View File
@@ -20,7 +20,7 @@
*/
/**
* Main include header for the SDL library, version 3.2.8
* Main include header for the SDL library, version 3.2.14
*
* It is almost always best to include just this one header instead of
* picking out individual headers included here. There are exceptions to
+8 -8
View File
@@ -1717,7 +1717,7 @@ typedef void (SDLCALL *SDL_AudioStreamCallback)(void *userdata, SDL_AudioStream
* audio to the stream during this call; if needed, the request that triggered
* this callback will obtain the new data immediately.
*
* The callback's `approx_request` argument is roughly how many bytes of
* The callback's `additional_amount` argument is roughly how many bytes of
* _unconverted_ data (in the stream's input format) is needed by the caller,
* although this may overestimate a little for safety. This takes into account
* how much is already in the stream and only asks for any extra necessary to
@@ -1762,13 +1762,13 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamGetCallback(SDL_AudioStream *
* The callback can (optionally) call SDL_GetAudioStreamData() to obtain audio
* from the stream during this call.
*
* The callback's `approx_request` argument is how many bytes of _converted_
* data (in the stream's output format) was provided by the caller, although
* this may underestimate a little for safety. This value might be less than
* what is currently available in the stream, if data was already there, and
* might be less than the caller provided if the stream needs to keep a buffer
* to aid in resampling. Which means the callback may be provided with zero
* bytes, and a different amount on each call.
* The callback's `additional_amount` argument is how many bytes of
* _converted_ data (in the stream's output format) was provided by the
* caller, although this may underestimate a little for safety. This value
* might be less than what is currently available in the stream, if data was
* already there, and might be less than the caller provided if the stream
* needs to keep a buffer to aid in resampling. Which means the callback may
* be provided with zero bytes, and a different amount on each call.
*
* The callback may call SDL_GetAudioStreamAvailable to see the total amount
* currently available to read from the stream, instead of the total provided
+2
View File
@@ -492,6 +492,8 @@ typedef struct SDL_MouseWheelEvent
SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
float mouse_x; /**< X coordinate, relative to window */
float mouse_y; /**< Y coordinate, relative to window */
Sint32 integer_x; /**< The amount scrolled horizontally, accumulated to whole scroll "ticks" (added in 3.2.12) */
Sint32 integer_y; /**< The amount scrolled vertically, accumulated to whole scroll "ticks" (added in 3.2.12) */
} SDL_MouseWheelEvent;
/**
+11 -11
View File
@@ -2467,9 +2467,9 @@ extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_CreateGPUShader(
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT`: (Direct3D 12 only)
* if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, clear
* the texture to a depth of this value. Defaults to zero.
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8`: (Direct3D 12
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER`: (Direct3D 12
* only) if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET,
* clear the texture to a stencil of this value. Defaults to zero.
* clear the texture to a stencil of this Uint8 value. Defaults to zero.
* - `SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING`: a name that can be displayed
* in debugging tools.
*
@@ -2495,13 +2495,13 @@ extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL SDL_CreateGPUTexture(
SDL_GPUDevice *device,
const SDL_GPUTextureCreateInfo *createinfo);
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT "SDL.gpu.texture.create.d3d12.clear.r"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT "SDL.gpu.texture.create.d3d12.clear.g"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT "SDL.gpu.texture.create.d3d12.clear.b"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT "SDL.gpu.texture.create.d3d12.clear.a"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT "SDL.gpu.texture.create.d3d12.clear.depth"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8 "SDL.gpu.texture.create.d3d12.clear.stencil"
#define SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING "SDL.gpu.texture.create.name"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT "SDL.gpu.texture.create.d3d12.clear.r"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT "SDL.gpu.texture.create.d3d12.clear.g"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT "SDL.gpu.texture.create.d3d12.clear.b"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT "SDL.gpu.texture.create.d3d12.clear.a"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT "SDL.gpu.texture.create.d3d12.clear.depth"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER "SDL.gpu.texture.create.d3d12.clear.stencil"
#define SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING "SDL.gpu.texture.create.name"
/**
* Creates a buffer object to be used in graphics or compute workflows.
@@ -3775,7 +3775,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseWindowFromGPUDevice(
* supported via SDL_WindowSupportsGPUPresentMode /
* SDL_WindowSupportsGPUSwapchainComposition prior to calling this function.
*
* SDL_GPU_PRESENTMODE_VSYNC and SDL_GPU_SWAPCHAINCOMPOSITION_SDR are always
* SDL_GPU_PRESENTMODE_VSYNC with SDL_GPU_SWAPCHAINCOMPOSITION_SDR are always
* supported.
*
* \param device a GPU context.
@@ -4145,7 +4145,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUTextureSupportsFormat(
* \param device a GPU context.
* \param format the texture format to check.
* \param sample_count the sample count to check.
* \returns a hardware-specific version of min(preferred, possible).
* \returns whether the sample count is supported for this texture format.
*
* \since This function is available since SDL 3.2.0.
*/
+18 -2
View File
@@ -1074,8 +1074,8 @@ extern "C" {
*
* By default, SDL will try all available GPU backends in a reasonable order
* until it finds one that can work, but this hint allows the app or user to
* force a specific target, such as "direct3d11" if, say, your hardware
* supports D3D12 but want to try using D3D11 instead.
* force a specific target, such as "direct3d12" if, say, your hardware
* supports Vulkan but you want to try using D3D12 instead.
*
* This hint should be set before any GPU functions are called.
*
@@ -3607,6 +3607,22 @@ extern "C" {
*/
#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
/**
* A variable controlling whether SDL should call XSelectInput() to enable
* input events on X11 windows wrapped by SDL windows.
*
* The variable can be set to the following values:
*
* - "0": Don't call XSelectInput(), assuming the native window code has done
* it already.
* - "1": Call XSelectInput() to enable input events. (default)
*
* This hint should be set before creating a window.
*
* \since This hint is available since SDL 3.2.10.
*/
#define SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT "SDL_VIDEO_X11_EXTERNAL_WINDOW_INPUT"
/**
* A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint
* should be used.
+4
View File
@@ -79,6 +79,10 @@ typedef enum SDL_PowerState
* It's possible a platform can only report battery percentage or time left
* but not both.
*
* On some platforms, retrieving power supply details might be expensive. If
* you want to display continuous status you could call this function every
* minute or so.
*
* \param seconds a pointer filled in with the seconds of battery life left,
* or NULL to ignore. This will be filled in with -1 if we
* can't determine a value or there is no battery.
+1 -2
View File
@@ -1607,8 +1607,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, S
* Return whether an explicit rectangle was set as the viewport.
*
* This is useful if you're saving and restoring the viewport and want to know
* whether you should restore a specific rectangle or NULL. Note that the
* viewport is always reset when changing rendering targets.
* whether you should restore a specific rectangle or NULL.
*
* Each render target has its own viewport. This function checks the viewport
* for the current render target.
+18 -2
View File
@@ -1299,8 +1299,11 @@ extern "C" {
*
* If `size` is 0, it will be set to 1.
*
* If you want to allocate memory aligned to a specific alignment, consider
* using SDL_aligned_alloc().
* If the allocation is successful, the returned pointer is guaranteed to be
* aligned to either the *fundamental alignment* (`alignof(max_align_t)` in
* C11 and later) or `2 * sizeof(void *)`, whichever is smaller. Use
* SDL_aligned_alloc() if you need to allocate memory aligned to an alignment
* greater than this guarantee.
*
* \param size the size to allocate.
* \returns a pointer to the allocated memory, or NULL if allocation failed.
@@ -1323,6 +1326,10 @@ extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_malloc(size_t size);
*
* If either of `nmemb` or `size` is 0, they will both be set to 1.
*
* If the allocation is successful, the returned pointer is guaranteed to be
* aligned to either the *fundamental alignment* (`alignof(max_align_t)` in
* C11 and later) or `2 * sizeof(void *)`, whichever is smaller.
*
* \param nmemb the number of elements in the array.
* \param size the size of each element of the array.
* \returns a pointer to the allocated array, or NULL if allocation failed.
@@ -1357,6 +1364,11 @@ extern SDL_DECLSPEC SDL_MALLOC SDL_ALLOC_SIZE2(1, 2) void * SDLCALL SDL_calloc(s
* - If it returns NULL (indicating failure), then `mem` will remain valid and
* must still be freed with SDL_free().
*
* If the allocation is successfully resized, the returned pointer is
* guaranteed to be aligned to either the *fundamental alignment*
* (`alignof(max_align_t)` in C11 and later) or `2 * sizeof(void *)`,
* whichever is smaller.
*
* \param mem a pointer to allocated memory to reallocate, or NULL.
* \param size the new size of the memory.
* \returns a pointer to the newly allocated memory, or NULL if allocation
@@ -5962,8 +5974,12 @@ size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
#endif
#ifndef _WIN32
/* strdup is not ANSI but POSIX, and its prototype might be hidden... */
/* not for windows: might conflict with string.h where strdup may have
* dllimport attribute: https://github.com/libsdl-org/SDL/issues/12948 */
char *strdup(const char *str);
#endif
/* Starting LLVM 16, the analyser errors out if these functions do not have
their prototype defined (clang-diagnostic-implicit-function-declaration) */
+127 -27
View File
@@ -82,6 +82,7 @@ typedef Uint32 SDL_SurfaceFlags;
*/
typedef enum SDL_ScaleMode
{
SDL_SCALEMODE_INVALID = -1,
SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */
SDL_SCALEMODE_LINEAR /**< linear filtering */
} SDL_ScaleMode;
@@ -156,6 +157,8 @@ typedef struct SDL_Surface SDL_Surface;
* \returns the new SDL_Surface structure that is created or NULL on failure;
* call SDL_GetError() for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_CreateSurfaceFrom
@@ -184,6 +187,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurface(int width, int heigh
* \returns the new SDL_Surface structure that is created or NULL on failure;
* call SDL_GetError() for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_CreateSurface
@@ -198,6 +203,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurfaceFrom(int width, int h
*
* \param surface the SDL_Surface to free.
*
* \threadsafety No other thread should be using the surface when it is freed.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_CreateSurface
@@ -233,6 +240,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
* \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface);
@@ -255,6 +264,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceColorspace
@@ -272,6 +283,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface,
* \returns the colorspace used by the surface, or SDL_COLORSPACE_UNKNOWN if
* the surface is NULL.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetSurfaceColorspace
@@ -300,6 +313,8 @@ extern SDL_DECLSPEC SDL_Colorspace SDLCALL SDL_GetSurfaceColorspace(SDL_Surface
* the surface didn't have an index format); call SDL_GetError() for
* more information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetPaletteColors
@@ -316,6 +331,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_CreateSurfacePalette(SDL_Surface *
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_CreatePalette
@@ -330,6 +347,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, SDL
* \returns a pointer to the palette used by the surface, or NULL if there is
* no palette used.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetSurfacePalette
@@ -353,6 +372,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_GetSurfacePalette(SDL_Surface *sur
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_RemoveSurfaceAlternateImages
@@ -367,6 +388,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_AddSurfaceAlternateImage(SDL_Surface *surfa
* \param surface the SDL_Surface structure to query.
* \returns true if alternate versions are available or false otherwise.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_AddSurfaceAlternateImage
@@ -392,6 +415,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasAlternateImages(SDL_Surface *surf
* failure; call SDL_GetError() for more information. This should be
* freed with SDL_free() when it is no longer needed.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_AddSurfaceAlternateImage
@@ -408,6 +433,8 @@ extern SDL_DECLSPEC SDL_Surface ** SDLCALL SDL_GetSurfaceImages(SDL_Surface *sur
*
* \param surface the SDL_Surface structure to update.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_AddSurfaceAlternateImage
@@ -432,6 +459,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_RemoveSurfaceAlternateImages(SDL_Surface *s
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe. The locking referred to by
* this function is making the pixels available for direct
* access, not thread-safe locking.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_MUSTLOCK
@@ -444,6 +475,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface);
*
* \param surface the SDL_Surface structure to be unlocked.
*
* \threadsafety This function is not thread safe. The locking referred to by
* this function is making the pixels available for direct
* access, not thread-safe locking.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_LockSurface
@@ -462,6 +497,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
* SDL_GetError() for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_DestroySurface
@@ -480,6 +517,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, bool
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
* SDL_GetError() for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_DestroySurface
@@ -504,6 +543,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file);
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_LoadBMP_IO
@@ -525,6 +566,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStre
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_LoadBMP
@@ -543,6 +586,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *f
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_BlitSurface
@@ -559,6 +604,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, bool en
* \param surface the SDL_Surface structure to query.
* \returns true if the surface is RLE enabled, false otherwise.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetSurfaceRLE
@@ -581,6 +628,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface);
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceColorKey
@@ -597,6 +646,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorKey(SDL_Surface *surface, bo
* \param surface the SDL_Surface structure to query.
* \returns true if the surface has a color key, false otherwise.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetSurfaceColorKey
@@ -617,6 +668,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasColorKey(SDL_Surface *surface);
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetSurfaceColorKey
@@ -640,6 +693,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Ui
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceColorMod
@@ -658,6 +713,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, Ui
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceAlphaMod
@@ -678,6 +735,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Ui
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceAlphaMod
@@ -693,6 +752,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Ui
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceColorMod
@@ -712,6 +773,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Ui
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceBlendMode
@@ -726,6 +789,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, S
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetSurfaceBlendMode
@@ -747,6 +812,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, S
* \returns true if the rectangle intersects the surface, otherwise false and
* blits will be completely clipped.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_GetSurfaceClipRect
@@ -766,6 +833,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, co
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_SetSurfaceClipRect
@@ -780,6 +849,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, SD
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip);
@@ -796,6 +867,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipM
* \returns a copy of the surface or NULL on failure; call SDL_GetError() for
* more information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_DestroySurface
@@ -815,6 +888,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_DuplicateSurface(SDL_Surface *surf
* \returns a copy of the surface or NULL on failure; call SDL_GetError() for
* more information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_DestroySurface
@@ -840,6 +915,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ScaleSurface(SDL_Surface *surface,
* \returns the new SDL_Surface structure that is created or NULL on failure;
* call SDL_GetError() for more information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_ConvertSurfaceAndColorspace
@@ -866,6 +943,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurface(SDL_Surface *surfac
* \returns the new SDL_Surface structure that is created or NULL on failure;
* call SDL_GetError() for more information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_ConvertSurface
@@ -887,6 +966,10 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurfaceAndColorspace(SDL_Su
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination pixels should not be used from two
* threads at once. It is safe to use the same source pixels
* from multiple threads.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_ConvertPixelsAndColorspace
@@ -916,6 +999,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixels(int width, int height, SDL_Pi
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination pixels should not be used from two
* threads at once. It is safe to use the same source pixels
* from multiple threads.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_ConvertPixels
@@ -940,6 +1027,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixelsAndColorspace(int width, int h
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination pixels should not be used from two
* threads at once. It is safe to use the same source pixels
* from multiple threads.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_PixelFormat src_format, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, bool linear);
@@ -955,6 +1046,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surface, bool linear);
@@ -975,6 +1068,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surfac
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, float g, float b, float a);
@@ -998,6 +1093,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r,
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_FillSurfaceRects
@@ -1023,6 +1120,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRect(SDL_Surface *dst, const SDL
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_FillSurfaceRect
@@ -1036,9 +1135,6 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SD
* If either `srcrect` or `dstrect` are NULL, the entire surface (`src` or
* `dst`) is copied while ensuring clipping to `dst->clip_rect`.
*
* The final blit rectangles are saved in `srcrect` and `dstrect` after all
* clipping is performed.
*
* The blit function should not be called on a locked surface.
*
* The blit semantics for surfaces with and without blending and colorkey are
@@ -1096,9 +1192,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SD
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.2.0.
*
@@ -1121,9 +1216,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rec
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.2.0.
*
@@ -1146,9 +1240,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUnchecked(SDL_Surface *src, cons
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.2.0.
*
@@ -1172,9 +1265,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const S
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.2.0.
*
@@ -1195,9 +1287,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.4.0.
*
@@ -1221,9 +1312,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_StretchSurface(SDL_Surface *src, const SDL_
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.2.0.
*
@@ -1251,9 +1341,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiled(SDL_Surface *src, const SD
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.2.0.
*
@@ -1288,9 +1377,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiledWithScale(SDL_Surface *src,
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety The same destination surface should not be used from two
* threads at once. It is safe to use the same source surface
* from multiple threads.
* \threadsafety Only one thread should be using the `src` and `dst` surfaces
* at any given time.
*
* \since This function is available since SDL 3.2.0.
*
@@ -1322,6 +1410,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface9Grid(SDL_Surface *src, const SD
* \param b the blue component of the pixel in the range 0-255.
* \returns a pixel value.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_MapSurfaceRGBA
@@ -1353,6 +1443,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGB(SDL_Surface *surface, Uint8
* \param a the alpha component of the pixel in the range 0-255.
* \returns a pixel value.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_MapSurfaceRGB
@@ -1382,6 +1474,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
@@ -1406,6 +1500,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, int x, int y, float *r, float *g, float *b, float *a);
@@ -1429,6 +1525,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface,
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
@@ -1449,6 +1547,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety This function is not thread safe.
*
* \since This function is available since SDL 3.2.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixelFloat(SDL_Surface *surface, int x, int y, float r, float g, float b, float a);
+1 -1
View File
@@ -62,7 +62,7 @@ extern "C" {
*
* \since This macro is available since SDL 3.2.0.
*/
#define SDL_MICRO_VERSION 8
#define SDL_MICRO_VERSION 14
/**
* This macro turns the version numbers into a numeric value.
+16 -4
View File
@@ -426,10 +426,10 @@ typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void *userdata, SDL_EGLDi
*/
typedef enum SDL_GLAttr
{
SDL_GL_RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 3. */
SDL_GL_GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 3. */
SDL_GL_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 2. */
SDL_GL_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 0. */
SDL_GL_RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 8. */
SDL_GL_GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 8. */
SDL_GL_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 8. */
SDL_GL_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 8. */
SDL_GL_BUFFER_SIZE, /**< the minimum number of bits for frame buffer size; defaults to 0. */
SDL_GL_DOUBLEBUFFER, /**< whether the output is single or double buffered; defaults to double buffering on. */
SDL_GL_DEPTH_SIZE, /**< the minimum number of bits in the depth buffer; defaults to 16. */
@@ -1041,6 +1041,10 @@ extern SDL_DECLSPEC SDL_Window ** SDLCALL SDL_GetWindows(int *count);
/**
* Create a window with the specified dimensions and flags.
*
* The window size is a request and may be different than expected based on
* the desktop layout and window manager policies. Your application should be
* prepared to handle a window of any size.
*
* `flags` may be any of the following OR'd together:
*
* - `SDL_WINDOW_FULLSCREEN`: fullscreen window at desktop resolution
@@ -1127,6 +1131,10 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int
/**
* Create a child popup window of the specified parent window.
*
* The window size is a request and may be different than expected based on
* the desktop layout and window manager policies. Your application should be
* prepared to handle a window of any size.
*
* The flags parameter **must** contain at least one of the following:
*
* - `SDL_WINDOW_TOOLTIP`: The popup window is a tooltip and will not pass any
@@ -1189,6 +1197,10 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
/**
* Create a window with the specified properties.
*
* The window size is a request and may be different than expected based on
* the desktop layout and window manager policies. Your application should be
* prepared to handle a window of any size.
*
* These are the supported properties:
*
* - `SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: true if the window should
+16 -18
View File
@@ -34,15 +34,7 @@
#endif
#ifdef SDL_PLATFORM_EMSCRIPTEN
#include <emscripten.h>
// older Emscriptens don't have this, but we need to for wasm64 compatibility.
#ifndef MAIN_THREAD_EM_ASM_PTR
#ifdef __wasm64__
#error You need to upgrade your Emscripten compiler to support wasm64
#else
#define MAIN_THREAD_EM_ASM_PTR MAIN_THREAD_EM_ASM_INT
#endif
#endif
#include <emscripten.h>
#endif
// The size of the stack buffer to use for rendering assert messages.
@@ -252,7 +244,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
for (;;) {
bool okay = true;
/* *INDENT-OFF* */ // clang-format off
char *buf = (char *) MAIN_THREAD_EM_ASM_PTR({
int reply = MAIN_THREAD_EM_ASM_INT({
var str =
UTF8ToString($0) + '\n\n' +
'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';
@@ -260,26 +252,32 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
if (reply === null) {
reply = "i";
}
return allocate(intArrayFromString(reply), 'i8', ALLOC_NORMAL);
return reply.length === 1 ? reply.charCodeAt(0) : -1;
}, message);
/* *INDENT-ON* */ // clang-format on
if (SDL_strcmp(buf, "a") == 0) {
switch (reply) {
case 'a':
state = SDL_ASSERTION_ABORT;
break;
#if 0 // (currently) no break functionality on Emscripten
} else if (SDL_strcmp(buf, "b") == 0) {
case 'b':
state = SDL_ASSERTION_BREAK;
break;
#endif
} else if (SDL_strcmp(buf, "r") == 0) {
case 'r':
state = SDL_ASSERTION_RETRY;
} else if (SDL_strcmp(buf, "i") == 0) {
break;
case 'i':
state = SDL_ASSERTION_IGNORE;
} else if (SDL_strcmp(buf, "A") == 0) {
break;
case 'A':
state = SDL_ASSERTION_ALWAYS_IGNORE;
} else {
break;
default:
okay = false;
break;
}
free(buf); // This should NOT be SDL_free()
if (okay) {
break;
+33
View File
@@ -22,6 +22,10 @@
#include "SDL_hints_c.h"
#ifdef SDL_PLATFORM_ANDROID
#include "core/android/SDL_android.h"
#endif
typedef struct SDL_HintWatch
{
SDL_HintCallback callback;
@@ -147,6 +151,13 @@ bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriori
}
}
#ifdef SDL_PLATFORM_ANDROID
if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
// Special handling for this hint, which needs to persist outside the normal application flow
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(value, false));
}
#endif // SDL_PLATFORM_ANDROID
SDL_UnlockProperties(hints);
return result;
@@ -185,6 +196,17 @@ bool SDL_ResetHint(const char *name)
result = true;
}
#ifdef SDL_PLATFORM_ANDROID
if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
// Special handling for this hint, which needs to persist outside the normal application flow
if (env) {
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(env, false));
} else {
Android_SetAllowRecreateActivity(false);
}
}
#endif // SDL_PLATFORM_ANDROID
SDL_UnlockProperties(hints);
return result;
@@ -210,6 +232,17 @@ static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, c
SDL_free(hint->value);
hint->value = NULL;
hint->priority = SDL_HINT_DEFAULT;
#ifdef SDL_PLATFORM_ANDROID
if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
// Special handling for this hint, which needs to persist outside the normal application flow
if (env) {
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(env, false));
} else {
Android_SetAllowRecreateActivity(false);
}
}
#endif // SDL_PLATFORM_ANDROID
}
void SDL_ResetHints(void)
+5 -1
View File
@@ -403,6 +403,10 @@ const char *SDL_GetPersistentString(const char *string)
static int PrefixMatch(const char *a, const char *b)
{
int matchlen = 0;
// Fixes the "HORI HORl Taiko No Tatsujin Drum Controller"
if (SDL_strncmp(a, "HORI ", 5) == 0 && SDL_strncmp(b, "HORl ", 5) == 0) {
return 5;
}
while (*a && *b) {
if (SDL_tolower((unsigned char)*a++) == SDL_tolower((unsigned char)*b++)) {
++matchlen;
@@ -424,8 +428,8 @@ char *SDL_CreateDeviceName(Uint16 vendor, Uint16 product, const char *vendor_nam
{ "ASTRO Gaming", "ASTRO" },
{ "Bensussen Deutsch & Associates,Inc.(BDA)", "BDA" },
{ "Guangzhou Chicken Run Network Technology Co., Ltd.", "GameSir" },
{ "HORI CO.,LTD", "HORI" },
{ "HORI CO.,LTD.", "HORI" },
{ "HORI CO.,LTD", "HORI" },
{ "Mad Catz Inc.", "Mad Catz" },
{ "Nintendo Co., Ltd.", "Nintendo" },
{ "NVIDIA Corporation ", "" },
+35 -7
View File
@@ -410,6 +410,7 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid,
SDL_LockRWLockForReading(current_audio.device_hash_lock);
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev);
if (logdev) {
SDL_assert(logdev->instance_id == devid);
device = logdev->physical_device;
SDL_assert(device != NULL);
RefPhysicalAudioDevice(device); // reference it, in case the logical device migrates to a new default.
@@ -459,6 +460,7 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // !
} else {
SDL_LockRWLockForReading(current_audio.device_hash_lock);
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device);
SDL_assert(device->instance_id == devid);
SDL_UnlockRWLock(current_audio.device_hash_lock);
if (!device) {
@@ -883,6 +885,7 @@ static bool SDLCALL FindLowestDeviceID(void *userdata, const SDL_HashTable *tabl
if (isphysical && (devid_recording == data->recording) && (devid < data->highest)) {
data->highest = devid;
data->result = (SDL_AudioDevice *) value;
SDL_assert(data->result->instance_id == devid);
}
return true; // keep iterating.
}
@@ -1051,7 +1054,10 @@ static bool SDLCALL DestroyOnePhysicalAudioDevice(void *userdata, const SDL_Hash
const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key;
const bool isphysical = !!(devid & (1<<1));
if (isphysical) {
DestroyPhysicalAudioDevice((SDL_AudioDevice *) value);
SDL_AudioDevice *dev = (SDL_AudioDevice *) value;
SDL_assert(dev->instance_id == devid);
DestroyPhysicalAudioDevice(dev);
}
return true; // keep iterating.
}
@@ -1256,11 +1262,11 @@ static int SDLCALL PlaybackAudioThread(void *devicep) // thread entry point
SDL_assert(!device->recording);
SDL_PlaybackAudioThreadSetup(device);
do {
while (SDL_PlaybackAudioThreadIterate(device)) {
if (!device->WaitDevice(device)) {
SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!)
}
} while (SDL_PlaybackAudioThreadIterate(device));
}
SDL_PlaybackAudioThreadShutdown(device);
return 0;
@@ -1464,6 +1470,7 @@ static bool SDLCALL FindAudioDeviceByCallback(void *userdata, const SDL_HashTabl
SDL_AudioDevice *device = (SDL_AudioDevice *) value;
if (data->callback(device, data->userdata)) { // found it?
data->retval = device;
SDL_assert(data->retval->instance_id == devid);
return false; // stop iterating, we found it.
}
}
@@ -1502,12 +1509,33 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle)
const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
{
// bit #1 of devid is set for physical devices and unset for logical.
const bool islogical = !(devid & (1<<1));
const char *result = NULL;
SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid);
if (device) {
result = SDL_GetPersistentString(device->name);
const void *vdev = NULL;
if (!SDL_GetCurrentAudioDriver()) {
SDL_SetError("Audio subsystem is not initialized");
} else {
// This does not call ObtainPhysicalAudioDevice() because the device's name never changes, so
// it doesn't have to lock the whole device. However, just to make sure the device pointer itself
// remains valid (in case the device is unplugged at the wrong moment), we hold the
// device_hash_lock while we copy the string.
SDL_LockRWLockForReading(current_audio.device_hash_lock);
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, &vdev);
if (!vdev) {
SDL_SetError("Invalid audio device instance ID");
} else if (islogical) {
const SDL_LogicalAudioDevice *logdev = (const SDL_LogicalAudioDevice *) vdev;
SDL_assert(logdev->instance_id == devid);
result = SDL_GetPersistentString(logdev->physical_device->name);
} else {
const SDL_AudioDevice *device = (const SDL_AudioDevice *) vdev;
SDL_assert(device->instance_id == devid);
result = SDL_GetPersistentString(device->name);
}
SDL_UnlockRWLock(current_audio.device_hash_lock);
}
ReleaseAudioDevice(device);
return result;
}
+57
View File
@@ -22,6 +22,10 @@
#include "SDL_sysaudio.h"
#ifdef SDL_NEON_INTRINSICS
#include <fenv.h>
#endif
#define DIVBY2147483648 0.0000000004656612873077392578125f // 0x1p-31f
// start fallback scalar converters
@@ -527,9 +531,27 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32* dst, const U
#endif
#ifdef SDL_NEON_INTRINSICS
// C99 requires that all code modifying floating point environment should
// be guarded by the STDC FENV_ACCESS pragma; otherwise, it's undefined
// behavior. However, the compiler support for this pragma is bad.
#if defined(__clang__)
#if __clang_major__ >= 12
#pragma STDC FENV_ACCESS ON
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (on)
#elif defined(__GNUC__)
// GCC does not support the pragma at all
#else
#pragma STDC FENV_ACCESS ON
#endif
static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("S8", "F32 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
CONVERT_16_REV({
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 7), 0);
@@ -549,11 +571,14 @@ static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_sam
vst1q_f32(&dst[i + 8], floats2);
vst1q_f32(&dst[i + 12], floats3);
})
fesetenv(&fenv);
}
static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("U8", "F32 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
uint8x16_t flipper = vdupq_n_u8(0x80);
@@ -575,11 +600,14 @@ static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_sam
vst1q_f32(&dst[i + 8], floats2);
vst1q_f32(&dst[i + 12], floats3);
})
fesetenv(&fenv);
}
static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("S16", "F32 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
CONVERT_16_REV({
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 15), 0);
@@ -597,11 +625,14 @@ static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_s
vst1q_f32(&dst[i + 8], floats2);
vst1q_f32(&dst[i + 12], floats3);
})
fesetenv(&fenv);
}
static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
CONVERT_16_FWD({
vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vld1_dup_s32(&src[i]), 31), 0);
@@ -621,11 +652,14 @@ static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_s
vst1q_f32(&dst[i + 8], floats2);
vst1q_f32(&dst[i + 12], floats3);
})
fesetenv(&fenv);
}
static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("F32", "S8 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
CONVERT_16_FWD({
vst1_lane_s8(&dst[i], vreinterpret_s8_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 3);
@@ -647,11 +681,14 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam
vst1q_s8(&dst[i], bytes);
})
fesetenv(&fenv);
}
static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("F32", "U8 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
uint8x16_t flipper = vdupq_n_u8(0x80);
@@ -679,11 +716,14 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam
vst1q_u8(&dst[i], bytes);
})
fesetenv(&fenv);
}
static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("F32", "S16 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
CONVERT_16_FWD({
vst1_lane_s16(&dst[i], vreinterpret_s16_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 1);
@@ -704,11 +744,14 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s
vst1q_s16(&dst[i], shorts0);
vst1q_s16(&dst[i + 8], shorts1);
})
fesetenv(&fenv);
}
static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_samples)
{
LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using NEON)");
fenv_t fenv;
feholdexcept(&fenv);
CONVERT_16_FWD({
vst1_lane_s32(&dst[i], vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31), 0);
@@ -728,6 +771,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s
vst1q_s32(&dst[i + 8], ints2);
vst1q_s32(&dst[i + 12], ints3);
})
fesetenv(&fenv);
}
static void SDL_Convert_Swap16_NEON(Uint16* dst, const Uint16* src, int num_samples)
@@ -767,6 +811,19 @@ static void SDL_Convert_Swap32_NEON(Uint32* dst, const Uint32* src, int num_samp
vst1q_u8((Uint8*)&dst[i + 12], ints3);
})
}
#if defined(__clang__)
#if __clang_major__ >= 12
#pragma STDC FENV_ACCESS DEFAULT
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (off)
#elif defined(__GNUC__)
//
#else
#pragma STDC FENV_ACCESS DEFAULT
#endif
#endif
#undef CONVERT_16_FWD
+7 -1
View File
@@ -308,6 +308,12 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
ctx.AAudioStreamBuilder_setFormat(builder, format);
ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq);
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
// If no specific buffer size has been requested, the device will pick the optimal
if(SDL_GetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES)) {
ctx.AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2 * device->sample_frames); // AAudio requires that the buffer capacity is at least
ctx.AAudioStreamBuilder_setFramesPerDataCallback(builder, device->sample_frames); // twice the size of the data callback buffer size
}
const aaudio_direction_t direction = (recording ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
ctx.AAudioStreamBuilder_setDirection(builder, direction);
@@ -366,7 +372,7 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
hidden->processed_bytes = 0;
hidden->callback_bytes = 0;
hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers);
hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers - 1);
if (!hidden->semaphore) {
LOGI("SDL Failed SDL_CreateSemaphore %s recording:%d", SDL_GetError(), recording);
return false;
+1 -1
View File
@@ -31,7 +31,7 @@ SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSamplesPerFrame, (AAudioStreamBuild
SDL_PROC(void, AAudioStreamBuilder_setFormat, (AAudioStreamBuilder * builder, aaudio_format_t format))
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSharingMode, (AAudioStreamBuilder * builder, aaudio_sharing_mode_t sharingMode))
SDL_PROC(void, AAudioStreamBuilder_setDirection, (AAudioStreamBuilder * builder, aaudio_direction_t direction))
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames))
SDL_PROC(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames))
SDL_PROC(void, AAudioStreamBuilder_setPerformanceMode, (AAudioStreamBuilder * builder, aaudio_performance_mode_t mode))
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) // API 28
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) // API 28
+8 -1
View File
@@ -1187,7 +1187,6 @@ static bool ALSA_OpenDevice(SDL_AudioDevice *device)
ALSA_snd_pcm_nonblock(cfg_ctx.device->hidden->pcm, 0);
}
#endif
ALSA_snd_pcm_start(cfg_ctx.device->hidden->pcm);
return true; // We're ready to rock and roll. :-)
err_cleanup_ctx:
@@ -1200,6 +1199,13 @@ err_free_device_hidden:
return false;
}
static void ALSA_ThreadInit(SDL_AudioDevice *device)
{
SDL_SetCurrentThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL);
// do snd_pcm_start as close to the first time we PlayDevice as possible to prevent an underrun at startup.
ALSA_snd_pcm_start(device->hidden->pcm);
}
static ALSA_Device *hotplug_devices = NULL;
static int hotplug_device_process(snd_ctl_t *ctl, snd_ctl_card_info_t *ctl_card_info, int dev_idx,
@@ -1497,6 +1503,7 @@ static bool ALSA_Init(SDL_AudioDriverImpl *impl)
impl->DetectDevices = ALSA_DetectDevices;
impl->OpenDevice = ALSA_OpenDevice;
impl->ThreadInit = ALSA_ThreadInit;
impl->WaitDevice = ALSA_WaitDevice;
impl->GetDeviceBuf = ALSA_GetDeviceBuf;
impl->PlayDevice = ALSA_PlayDevice;
+12 -2
View File
@@ -1118,7 +1118,13 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
if (!stream_name || *stream_name == '\0') {
stream_name = "Audio Stream";
if (app_name) {
stream_name = app_name;
} else if (app_id) {
stream_name = app_id;
} else {
stream_name = "SDL Audio Stream";
}
}
/*
@@ -1187,7 +1193,11 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%i", device->sample_frames, device->spec.freq);
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", device->spec.freq);
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware.
// UPDATE: This prevents users from moving the audio to a new sink (device) using standard tools. This is slightly in conflict
// with how SDL wants to manage audio devices, but if people want to do it, we should let them, so this is commented out
// for now. We might revisit later.
//PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware.
if (node_id != PW_ID_ANY) {
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
+5 -2
View File
@@ -409,7 +409,7 @@ static bool PULSEAUDIO_WaitDevice(SDL_AudioDevice *device)
struct SDL_PrivateAudioData *h = device->hidden;
bool result = true;
//SDL_Log("PULSEAUDIO PLAYDEVICE START! mixlen=%d", available);
//SDL_Log("PULSEAUDIO WAITDEVICE START! mixlen=%d", available);
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
@@ -701,7 +701,10 @@ static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
PULSEAUDIO_pa_stream_set_state_callback(h->stream, PulseStreamStateChangeCallback, NULL);
// SDL manages device moves if the default changes, so don't ever let Pulse automatically migrate this stream.
flags |= PA_STREAM_DONT_MOVE;
// UPDATE: This prevents users from moving the audio to a new sink (device) using standard tools. This is slightly in conflict
// with how SDL wants to manage audio devices, but if people want to do it, we should let them, so this is commented out
// for now. We might revisit later.
//flags |= PA_STREAM_DONT_MOVE;
const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path;
if (recording) {
+2 -1
View File
@@ -130,7 +130,8 @@ static bool VITAAUD_OpenDevice(SDL_AudioDevice *device)
static bool VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
{
return (sceAudioOutOutput(device->hidden->port, buffer) == 0);
// sceAudioOutOutput returns amount of samples queued or < 0 on error
return (sceAudioOutOutput(device->hidden->port, buffer) >= 0);
}
// This function waits until it is possible to write a full sound buffer
+17 -1
View File
@@ -751,6 +751,8 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
typedef int (*SDL_main_func)(int argc, char *argv[]);
static int run_count = 0;
static bool allow_recreate_activity;
static bool allow_recreate_activity_set;
JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
JNIEnv *env, jclass jcls)
@@ -760,10 +762,16 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
return tmp;
}
void Android_SetAllowRecreateActivity(bool enabled)
{
allow_recreate_activity = enabled;
allow_recreate_activity_set = true;
}
JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(nativeAllowRecreateActivity)(
JNIEnv *env, jclass jcls)
{
return SDL_GetHintBoolean(SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY, false);
return allow_recreate_activity;
}
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeInitMainThread)(
@@ -1526,6 +1534,14 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
// Note that we call setenv() directly to avoid affecting SDL environments
setenv(utfname, utfvalue, 1); // This should NOT be SDL_setenv()
if (SDL_strcmp(utfname, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
// Special handling for this hint, which needs to persist outside the normal application flow
// Only set this the first time we run, in case it's been set by the application via SDL_SetHint()
if (!allow_recreate_activity_set) {
Android_SetAllowRecreateActivity(SDL_GetStringBoolean(utfvalue, false));
}
}
(*env)->ReleaseStringUTFChars(env, name, utfname);
(*env)->ReleaseStringUTFChars(env, value, utfvalue);
}
+2
View File
@@ -55,6 +55,8 @@ bool Android_WaitLifecycleEvent(SDL_AndroidLifecycleEvent *event, Sint64 timeout
void Android_LockActivityMutex(void);
void Android_UnlockActivityMutex(void);
void Android_SetAllowRecreateActivity(bool enabled);
// Interface from the SDL library into the Android Java activity
extern void Android_JNI_SetActivityTitle(const char *title);
extern void Android_JNI_SetWindowStyle(bool fullscreen);
+3 -3
View File
@@ -330,10 +330,10 @@ void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect)
winrect->bottom = sdlrect->y + sdlrect->h - 1;
}
BOOL WIN_IsRectEmpty(const RECT *rect)
bool WIN_WindowRectValid(const RECT *rect)
{
// Calculating this manually because Xbox does not support Win32 IsRectEmpty.
return (rect->right <= rect->left) || (rect->bottom <= rect->top);
// A window can be resized to zero height, but not zero width
return (rect->right > 0);
}
// Some GUIDs we need to know without linking to libraries that aren't available before Vista.
+2 -2
View File
@@ -156,8 +156,8 @@ extern BOOL WIN_IsEqualIID(REFIID a, REFIID b);
extern void WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect);
extern void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect);
// Returns true if the rect is empty
extern BOOL WIN_IsRectEmpty(const RECT *rect);
// Returns false if a window client rect is not valid
bool WIN_WindowRectValid(const RECT *rect);
extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat);
+4 -4
View File
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,2,8,0
PRODUCTVERSION 3,2,8,0
FILEVERSION 3,2,14,0
PRODUCTVERSION 3,2,14,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "3, 2, 8, 0\0"
VALUE "FileVersion", "3, 2, 14, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL3.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "3, 2, 8, 0\0"
VALUE "ProductVersion", "3, 2, 14, 0\0"
END
END
BLOCK "VarFileInfo"
+25 -2
View File
@@ -85,7 +85,9 @@
#include <kernel.h>
#include <swis.h>
#endif
#ifdef SDL_PLATFORM_3DS
#include <3ds.h>
#endif
#ifdef SDL_PLATFORM_PS2
#include <kernel.h>
#endif
@@ -113,7 +115,11 @@
#define CPU_CFG2_LSX (1 << 6)
#define CPU_CFG2_LASX (1 << 7)
#if defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) && !defined(SDL_PLATFORM_MACOS) && !defined(SDL_PLATFORM_OPENBSD) && !defined(SDL_PLATFORM_FREEBSD)
#if !defined(SDL_CPUINFO_DISABLED) && \
!((defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__))) || (defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__))) && \
!(defined(SDL_PLATFORM_FREEBSD) && defined(__powerpc__)) && \
!(defined(SDL_PLATFORM_LINUX) && defined(__powerpc__) && defined(HAVE_GETAUXVAL)) && \
defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP)
/* This is the brute force way of detecting instruction sets...
the idea is borrowed from the libmpeg2 library - thanks!
*/
@@ -342,6 +348,8 @@ static int CPU_haveAltiVec(void)
elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures));
altivec = cpufeatures & PPC_FEATURE_HAS_ALTIVEC;
return altivec;
#elif defined(SDL_PLATFORM_LINUX) && defined(__powerpc__) && defined(HAVE_GETAUXVAL)
altivec = getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC;
#elif defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP)
void (*handler)(int sig);
handler = signal(SIGILL, illegal_instruction);
@@ -642,6 +650,15 @@ int SDL_GetNumLogicalCPUCores(void)
GetSystemInfo(&info);
SDL_NumLogicalCPUCores = info.dwNumberOfProcessors;
}
#endif
#ifdef SDL_PLATFORM_3DS
if (SDL_NumLogicalCPUCores <= 0) {
bool isNew3DS = false;
APT_CheckNew3DS(&isNew3DS);
// 1 core is always dedicated to the OS
// Meaning that the New3DS has 3 available core, and the Old3DS only one.
SDL_NumLogicalCPUCores = isNew3DS ? 4 : 2;
}
#endif
// There has to be at least 1, right? :)
if (SDL_NumLogicalCPUCores <= 0) {
@@ -1156,6 +1173,12 @@ int SDL_GetSystemRAM(void)
}
}
#endif
#ifdef SDL_PLATFORM_3DS
if (SDL_SystemRAM <= 0) {
// The New3DS has 255MiB, the Old3DS 127MiB
SDL_SystemRAM = (int)(osGetMemRegionSize(MEMREGION_ALL) / (1024 * 1024));
}
#endif
#ifdef SDL_PLATFORM_VITA
if (SDL_SystemRAM <= 0) {
/* Vita has 512MiB on SoC, that's split into 256MiB(+109MiB in extended memory mode) for app
+36 -11
View File
@@ -27,6 +27,35 @@
#import <Cocoa/Cocoa.h>
#import <UniformTypeIdentifiers/UTType.h>
static void AddFileExtensionType(NSMutableArray *types, const char *pattern_ptr)
{
if (!*pattern_ptr) {
return; // in case the string had an extra ';' at the end.
}
// -[UTType typeWithFilenameExtension] will return nil if there's a period in the string. It's better to
// allow too many files than not allow the one the user actually needs, so just take the part after the '.'
const char *dot = SDL_strrchr(pattern_ptr, '.');
NSString *extstr = [NSString stringWithFormat: @"%s", dot ? (dot + 1) : pattern_ptr];
if (@available(macOS 11.0, *)) {
UTType *uttype = [UTType typeWithFilenameExtension:extstr];
if (uttype) { // still failed? Don't add the pattern. This is what the pre-macOS11 path does internally anyhow.
[types addObject:uttype];
}
} else {
[types addObject:extstr];
}
}
static void ReactivateAfterDialog(void)
{
for (NSRunningApplication *i in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
[i activateWithOptions:0];
break;
}
[NSApp activateIgnoringOtherApps:YES];
}
void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
{
SDL_Window* window = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL);
@@ -87,7 +116,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
if (filters) {
// On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString
NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters ];
NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters];
int has_all_files = 0;
for (int i = 0; i < nfilters; i++) {
@@ -102,21 +131,14 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
for (char *c = pattern; *c; c++) {
if (*c == ';') {
*c = '\0';
if(@available(macOS 11.0, *)) {
[types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]];
} else {
[types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]];
}
AddFileExtensionType(types, pattern_ptr);
pattern_ptr = c + 1;
} else if (*c == '*') {
has_all_files = 1;
}
}
if(@available(macOS 11.0, *)) {
[types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]];
} else {
[types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]];
}
AddFileExtensionType(types, pattern_ptr); // get the last piece of the string.
SDL_free(pattern);
}
@@ -163,6 +185,8 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
const char *files[1] = { NULL };
callback(userdata, files, -1);
}
ReactivateAfterDialog();
}];
} else {
if ([dialog runModal] == NSModalResponseOK) {
@@ -182,6 +206,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
const char *files[1] = { NULL };
callback(userdata, files, -1);
}
ReactivateAfterDialog();
}
}
+9 -1
View File
@@ -516,6 +516,14 @@ static void ShowFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_
filters_str = win_get_filters(filters, nfilters);
DWORD flags = 0;
if (allow_many) {
flags |= OFN_ALLOWMULTISELECT;
}
if (is_save) {
flags |= OFN_OVERWRITEPROMPT;
}
if (!filters_str && filters) {
callback(userdata, NULL, -1);
SDL_free(args);
@@ -526,7 +534,7 @@ static void ShowFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_
args->filters_str = filters_str;
args->default_file = default_location ? SDL_strdup(default_location) : NULL;
args->parent = window;
args->flags = allow_many ? OFN_ALLOWMULTISELECT : 0;
args->flags = flags;
args->callback = callback;
args->userdata = userdata;
args->title = title ? SDL_strdup(title) : NULL;
+7 -8
View File
@@ -633,9 +633,10 @@ static void SDL_LogEvent(const SDL_Event *event)
#undef PRINT_MBUTTON_EVENT
SDL_EVENT_CASE(SDL_EVENT_MOUSE_WHEEL)
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u x=%g y=%g direction=%s)",
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u x=%g y=%g integer_x=%d integer_y=%d direction=%s)",
(uint)event->wheel.timestamp, (uint)event->wheel.windowID,
(uint)event->wheel.which, event->wheel.x, event->wheel.y,
(int)event->wheel.integer_x, (int)event->wheel.integer_y,
event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
break;
@@ -1379,9 +1380,7 @@ bool SDL_RunOnMainThread(SDL_MainThreadCallback callback, void *userdata, bool w
return true;
}
// Maximum wait of 30 seconds to prevent deadlocking forever
const Sint32 MAX_CALLBACK_WAIT = 30 * 1000;
SDL_WaitSemaphoreTimeout(entry->semaphore, MAX_CALLBACK_WAIT);
SDL_WaitSemaphore(entry->semaphore);
switch (SDL_GetAtomicInt(&entry->state)) {
case SDL_MAIN_CALLBACK_COMPLETE:
@@ -1823,7 +1822,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled)
Uint8 lo = (type & 0xff);
if (SDL_disabled_events[hi] &&
(SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) {
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
current_state = false;
} else {
current_state = true;
@@ -1832,7 +1831,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled)
if ((enabled != false) != current_state) {
if (enabled) {
SDL_assert(SDL_disabled_events[hi] != NULL);
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1 << (lo & 31));
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1U << (lo & 31));
// Gamepad events depend on joystick events
switch (type) {
@@ -1863,7 +1862,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled)
}
// Out of memory, nothing we can do...
if (SDL_disabled_events[hi]) {
SDL_disabled_events[hi]->bits[lo / 32] |= (1 << (lo & 31));
SDL_disabled_events[hi]->bits[lo / 32] |= (1U << (lo & 31));
SDL_FlushEvent(type);
}
}
@@ -1882,7 +1881,7 @@ bool SDL_EventEnabled(Uint32 type)
Uint8 lo = (type & 0xff);
if (SDL_disabled_events[hi] &&
(SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) {
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
return false;
} else {
return true;
+3 -3
View File
@@ -747,7 +747,7 @@ void SDL_SendKeyboardText(const char *text)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
if (!SDL_TextInputActive(keyboard->focus)) {
if (!keyboard->focus || !SDL_TextInputActive(keyboard->focus)) {
return;
}
@@ -778,7 +778,7 @@ void SDL_SendEditingText(const char *text, int start, int length)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
if (!SDL_TextInputActive(keyboard->focus)) {
if (!keyboard->focus || !SDL_TextInputActive(keyboard->focus)) {
return;
}
@@ -838,7 +838,7 @@ void SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int se
{
SDL_Keyboard *keyboard = &SDL_keyboard;
if (!SDL_TextInputActive(keyboard->focus)) {
if (!keyboard->focus || !SDL_TextInputActive(keyboard->focus)) {
return;
}
+46 -2
View File
@@ -234,6 +234,17 @@ static void SDLCALL SDL_MouseRelativeCursorVisibleChanged(void *userdata, const
SDL_SetCursor(NULL); // Update cursor visibility
}
static void SDLCALL SDL_MouseIntegerModeChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
if (hint && *hint) {
mouse->integer_mode_flags = (Uint8)SDL_atoi(hint);
} else {
mouse->integer_mode_flags = 0;
}
}
// Public functions
bool SDL_PreInitMouse(void)
{
@@ -288,6 +299,9 @@ bool SDL_PreInitMouse(void)
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
SDL_MouseRelativeCursorVisibleChanged, mouse);
SDL_AddHintCallback("SDL_MOUSE_INTEGER_MODE",
SDL_MouseIntegerModeChanged, mouse);
mouse->was_touch_mouse_events = false; // no touch to mouse movement event pending
mouse->cursor_shown = true;
@@ -720,12 +734,22 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL
y *= mouse->normal_speed_scale;
}
}
if (mouse->integer_mode_flags & 1) {
// Accumulate the fractional relative motion and only process the integer portion
mouse->integer_mode_residual_motion_x = SDL_modff(mouse->integer_mode_residual_motion_x + x, &x);
mouse->integer_mode_residual_motion_y = SDL_modff(mouse->integer_mode_residual_motion_y + y, &y);
}
xrel = x;
yrel = y;
x = (mouse->last_x + xrel);
y = (mouse->last_y + yrel);
ConstrainMousePosition(mouse, window, &x, &y);
} else {
if (mouse->integer_mode_flags & 1) {
// Discard the fractional component from absolute coordinates
x = SDL_truncf(x);
y = SDL_truncf(y);
}
ConstrainMousePosition(mouse, window, &x, &y);
if (mouse->has_position) {
xrel = x - mouse->last_x;
@@ -1004,6 +1028,8 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI
// Post the event, if desired
if (SDL_EventEnabled(SDL_EVENT_MOUSE_WHEEL)) {
float integer_x, integer_y;
if (!mouse->relative_mode || mouse->warp_emulation_active) {
// We're not in relative mode, so all mouse events are global mouse events
mouseID = SDL_GLOBAL_MOUSE_ID;
@@ -1014,11 +1040,26 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI
event.common.timestamp = timestamp;
event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
event.wheel.which = mouseID;
event.wheel.x = x;
event.wheel.y = y;
event.wheel.direction = direction;
event.wheel.mouse_x = mouse->x;
event.wheel.mouse_y = mouse->y;
mouse->residual_scroll_x = SDL_modff(mouse->residual_scroll_x + x, &integer_x);
event.wheel.integer_x = (Sint32)integer_x;
mouse->residual_scroll_y = SDL_modff(mouse->residual_scroll_y + y, &integer_y);
event.wheel.integer_y = (Sint32)integer_y;
// Return the accumulated values in x/y when integer wheel mode is enabled.
// This is necessary for compatibility with sdl2-compat 2.32.54.
if (mouse->integer_mode_flags & 2) {
event.wheel.x = integer_x;
event.wheel.y = integer_y;
} else {
event.wheel.x = x;
event.wheel.y = y;
}
SDL_PushEvent(&event);
}
}
@@ -1108,6 +1149,9 @@ void SDL_QuitMouse(void)
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
SDL_MouseRelativeCursorVisibleChanged, mouse);
SDL_RemoveHintCallback("SDL_MOUSE_INTEGER_MODE",
SDL_MouseIntegerModeChanged, mouse);
for (int i = SDL_mouse_count; i--; ) {
SDL_RemoveMouse(SDL_mice[i].instance_id, false);
}
+7
View File
@@ -91,6 +91,11 @@ typedef struct
void (*ApplySystemScale)(void *internal, Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float *x, float *y);
void *system_scale_data;
// integer mode data
Uint8 integer_mode_flags; // 1 to enable mouse quantization, 2 to enable wheel quantization
float integer_mode_residual_motion_x;
float integer_mode_residual_motion_y;
// Data common to all mice
SDL_Window *focus;
float x;
@@ -98,6 +103,8 @@ typedef struct
float x_accu;
float y_accu;
float last_x, last_y; // the last reported x and y coordinates
float residual_scroll_x;
float residual_scroll_y;
double click_motion_x;
double click_motion_y;
bool has_position;
+11 -2
View File
@@ -565,10 +565,19 @@ void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
event.pbutton.down = down;
SDL_PushEvent(&event);
if (window && (pen_touching == instance_id)) {
if (window && (!pen_touching || (pen_touching == instance_id))) {
SDL_Mouse *mouse = SDL_GetMouse();
if (mouse && mouse->pen_mouse_events) {
SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, button + 1, down);
static const Uint8 mouse_buttons[] = {
SDL_BUTTON_LEFT,
SDL_BUTTON_RIGHT,
SDL_BUTTON_MIDDLE,
SDL_BUTTON_X1,
SDL_BUTTON_X2
};
if (button < SDL_arraysize(mouse_buttons)) {
SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, mouse_buttons[button], down);
}
}
}
}
+72 -4
View File
@@ -56,11 +56,43 @@
}
#define CHECK_RENDERPASS \
if (!((Pass *)render_pass)->in_progress) { \
if (!((RenderPass *)render_pass)->in_progress) { \
SDL_assert_release(!"Render pass not in progress!"); \
return; \
}
#define CHECK_SAMPLER_TEXTURES \
RenderPass *rp = (RenderPass *)render_pass; \
for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
if (rp->color_targets[color_target_index] == texture_sampler_bindings[texture_sampler_index].texture) { \
SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a sampler!"); \
} \
} \
} \
\
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == texture_sampler_bindings[texture_sampler_index].texture) { \
SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a sampler!"); \
} \
}
#define CHECK_STORAGE_TEXTURES \
RenderPass *rp = (RenderPass *)render_pass; \
for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
if (rp->color_targets[color_target_index] == storage_textures[texture_sampler_index]) { \
SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a storage texture!"); \
} \
} \
} \
\
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == storage_textures[texture_sampler_index]) { \
SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a storage texture!"); \
} \
}
#define CHECK_GRAPHICS_PIPELINE_BOUND \
if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \
SDL_assert_release(!"Graphics pipeline not bound!"); \
@@ -137,7 +169,7 @@
((CommandBufferCommonHeader *)command_buffer)->device
#define RENDERPASS_COMMAND_BUFFER \
((Pass *)render_pass)->command_buffer
((RenderPass *)render_pass)->command_buffer
#define RENDERPASS_DEVICE \
((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device
@@ -1523,6 +1555,13 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
commandBufferHeader->render_pass.in_progress = true;
for (Uint32 i = 0; i < num_color_targets; i += 1) {
commandBufferHeader->render_pass.color_targets[i] = color_target_infos[i].texture;
}
commandBufferHeader->render_pass.num_color_targets = num_color_targets;
if (depth_stencil_target_info != NULL) {
commandBufferHeader->render_pass.depth_stencil_target = depth_stencil_target_info->texture;
}
return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass);
}
@@ -1696,6 +1735,11 @@ void SDL_BindGPUVertexSamplers(
if (RENDERPASS_DEVICE->debug_mode) {
CHECK_RENDERPASS
if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation)
{
CHECK_SAMPLER_TEXTURES
}
}
RENDERPASS_DEVICE->BindVertexSamplers(
@@ -1722,6 +1766,7 @@ void SDL_BindGPUVertexStorageTextures(
if (RENDERPASS_DEVICE->debug_mode) {
CHECK_RENDERPASS
CHECK_STORAGE_TEXTURES
}
RENDERPASS_DEVICE->BindVertexStorageTextures(
@@ -1774,6 +1819,11 @@ void SDL_BindGPUFragmentSamplers(
if (RENDERPASS_DEVICE->debug_mode) {
CHECK_RENDERPASS
if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation)
{
CHECK_SAMPLER_TEXTURES
}
}
RENDERPASS_DEVICE->BindFragmentSamplers(
@@ -1800,6 +1850,7 @@ void SDL_BindGPUFragmentStorageTextures(
if (RENDERPASS_DEVICE->debug_mode) {
CHECK_RENDERPASS
CHECK_STORAGE_TEXTURES
}
RENDERPASS_DEVICE->BindFragmentStorageTextures(
@@ -1960,6 +2011,12 @@ void SDL_EndGPURenderPass(
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
commandBufferCommonHeader->render_pass.in_progress = false;
for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
{
commandBufferCommonHeader->render_pass.color_targets[i] = NULL;
}
commandBufferCommonHeader->render_pass.num_color_targets = 0;
commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
commandBufferCommonHeader->graphics_pipeline_bound = false;
}
@@ -2528,11 +2585,19 @@ void SDL_GenerateMipmapsForGPUTexture(
SDL_assert_release(!"GenerateMipmaps texture must be created with SAMPLER and COLOR_TARGET usage flags!");
return;
}
CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
commandBufferHeader->ignore_render_pass_texture_validation = true;
}
COMMAND_BUFFER_DEVICE->GenerateMipmaps(
command_buffer,
texture);
if (COMMAND_BUFFER_DEVICE->debug_mode) {
CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
commandBufferHeader->ignore_render_pass_texture_validation = false;
}
}
void SDL_BlitGPUTexture(
@@ -2646,8 +2711,11 @@ bool SDL_ClaimWindowForGPUDevice(
{
CHECK_DEVICE_MAGIC(device, false);
if (window == NULL) {
SDL_InvalidParamError("window");
return false;
return SDL_InvalidParamError("window");
}
if ((window->flags & SDL_WINDOW_TRANSPARENT) != 0) {
return SDL_SetError("The GPU API doesn't support transparent windows");
}
return device->ClaimWindow(
+27 -16
View File
@@ -24,6 +24,21 @@
#ifndef SDL_GPU_DRIVER_H
#define SDL_GPU_DRIVER_H
// GraphicsDevice Limits
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
#define MAX_STORAGE_TEXTURES_PER_STAGE 8
#define MAX_STORAGE_BUFFERS_PER_STAGE 8
#define MAX_UNIFORM_BUFFERS_PER_STAGE 4
#define MAX_COMPUTE_WRITE_TEXTURES 8
#define MAX_COMPUTE_WRITE_BUFFERS 8
#define UNIFORM_BUFFER_SIZE 32768
#define MAX_VERTEX_BUFFERS 16
#define MAX_VERTEX_ATTRIBUTES 16
#define MAX_COLOR_TARGET_BINDINGS 4
#define MAX_PRESENT_COUNT 16
#define MAX_FRAMES_IN_FLIGHT 3
// Common Structs
typedef struct Pass
@@ -32,16 +47,27 @@ typedef struct Pass
bool in_progress;
} Pass;
typedef struct RenderPass
{
SDL_GPUCommandBuffer *command_buffer;
bool in_progress;
SDL_GPUTexture *color_targets[MAX_COLOR_TARGET_BINDINGS];
Uint32 num_color_targets;
SDL_GPUTexture *depth_stencil_target;
} RenderPass;
typedef struct CommandBufferCommonHeader
{
SDL_GPUDevice *device;
Pass render_pass;
RenderPass render_pass;
bool graphics_pipeline_bound;
Pass compute_pass;
bool compute_pipeline_bound;
Pass copy_pass;
bool swapchain_texture_acquired;
bool submitted;
// used to avoid tripping assert on GenerateMipmaps
bool ignore_render_pass_texture_validation;
} CommandBufferCommonHeader;
typedef struct TextureCommonHeader
@@ -385,21 +411,6 @@ static inline Uint32 BytesPerRow(
return blocksPerRow * SDL_GPUTextureFormatTexelBlockSize(format);
}
// GraphicsDevice Limits
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
#define MAX_STORAGE_TEXTURES_PER_STAGE 8
#define MAX_STORAGE_BUFFERS_PER_STAGE 8
#define MAX_UNIFORM_BUFFERS_PER_STAGE 4
#define MAX_COMPUTE_WRITE_TEXTURES 8
#define MAX_COMPUTE_WRITE_BUFFERS 8
#define UNIFORM_BUFFER_SIZE 32768
#define MAX_VERTEX_BUFFERS 16
#define MAX_VERTEX_ATTRIBUTES 16
#define MAX_COLOR_TARGET_BINDINGS 4
#define MAX_PRESENT_COUNT 16
#define MAX_FRAMES_IN_FLIGHT 3
// Internal Macros
#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \
+154 -30
View File
@@ -475,6 +475,115 @@ static DXGI_FORMAT SDLToD3D12_DepthFormat[] = {
};
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_DepthFormat, SDL_arraysize(SDLToD3D12_DepthFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
static DXGI_FORMAT SDLToD3D12_TypelessFormat[] = {
DXGI_FORMAT_UNKNOWN, // INVALID
DXGI_FORMAT_UNKNOWN, // A8_UNORM
DXGI_FORMAT_UNKNOWN, // R8_UNORM
DXGI_FORMAT_UNKNOWN, // R8G8_UNORM
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM
DXGI_FORMAT_UNKNOWN, // R16_UNORM
DXGI_FORMAT_UNKNOWN, // R16G16_UNORM
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UNORM
DXGI_FORMAT_UNKNOWN, // R10G10B10A2_UNORM
DXGI_FORMAT_UNKNOWN, // B5G6R5_UNORM
DXGI_FORMAT_UNKNOWN, // B5G5R5A1_UNORM
DXGI_FORMAT_UNKNOWN, // B4G4R4A4_UNORM
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM
DXGI_FORMAT_UNKNOWN, // BC1_UNORM
DXGI_FORMAT_UNKNOWN, // BC2_UNORM
DXGI_FORMAT_UNKNOWN, // BC3_UNORM
DXGI_FORMAT_UNKNOWN, // BC4_UNORM
DXGI_FORMAT_UNKNOWN, // BC5_UNORM
DXGI_FORMAT_UNKNOWN, // BC7_UNORM
DXGI_FORMAT_UNKNOWN, // BC6H_FLOAT
DXGI_FORMAT_UNKNOWN, // BC6H_UFLOAT
DXGI_FORMAT_UNKNOWN, // R8_SNORM
DXGI_FORMAT_UNKNOWN, // R8G8_SNORM
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_SNORM
DXGI_FORMAT_UNKNOWN, // R16_SNORM
DXGI_FORMAT_UNKNOWN, // R16G16_SNORM
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_SNORM
DXGI_FORMAT_UNKNOWN, // R16_FLOAT
DXGI_FORMAT_UNKNOWN, // R16G16_FLOAT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_FLOAT
DXGI_FORMAT_UNKNOWN, // R32_FLOAT
DXGI_FORMAT_UNKNOWN, // R32G32_FLOAT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_FLOAT
DXGI_FORMAT_UNKNOWN, // R11G11B10_UFLOAT
DXGI_FORMAT_UNKNOWN, // R8_UINT
DXGI_FORMAT_UNKNOWN, // R8G8_UINT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UINT
DXGI_FORMAT_UNKNOWN, // R16_UINT
DXGI_FORMAT_UNKNOWN, // R16G16_UINT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UINT
DXGI_FORMAT_UNKNOWN, // R32_UINT
DXGI_FORMAT_UNKNOWN, // R32G32_UINT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_UINT
DXGI_FORMAT_UNKNOWN, // R8_INT
DXGI_FORMAT_UNKNOWN, // R8G8_INT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_INT
DXGI_FORMAT_UNKNOWN, // R16_INT
DXGI_FORMAT_UNKNOWN, // R16G16_INT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_INT
DXGI_FORMAT_UNKNOWN, // R32_INT
DXGI_FORMAT_UNKNOWN, // R32G32_INT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_INT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC1_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC2_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC3_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC7_UNORM_SRGB
DXGI_FORMAT_R16_TYPELESS, // D16_UNORM
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM
DXGI_FORMAT_R32_TYPELESS, // D32_FLOAT
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM_S8_UINT
DXGI_FORMAT_R32G8X24_TYPELESS, // D32_FLOAT_S8_UINT
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
};
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TypelessFormat, SDL_arraysize(SDLToD3D12_TypelessFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
D3D12_COMPARISON_FUNC_NEVER, // INVALID
D3D12_COMPARISON_FUNC_NEVER, // NEVER
@@ -3188,6 +3297,10 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
D3D12_CLEAR_VALUE clearValue;
DXGI_FORMAT format;
bool useClearValue = false;
bool needsSRV =
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) ||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) ||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ);
bool needsUAV =
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE);
@@ -3207,6 +3320,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
useClearValue = true;
clearValue.Format = format;
clearValue.Color[0] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT, 0);
clearValue.Color[1] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT, 0);
clearValue.Color[2] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT, 0);
@@ -3216,9 +3330,10 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
useClearValue = true;
clearValue.Format = SDLToD3D12_DepthFormat[createinfo->format];
clearValue.DepthStencil.Depth = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT, 0);
clearValue.DepthStencil.Stencil = (UINT8)SDL_GetNumberProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8, 0);
format = SDLToD3D12_DepthFormat[createinfo->format];
clearValue.DepthStencil.Stencil = (UINT8)SDL_GetNumberProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER, 0);
format = needsSRV ? SDLToD3D12_TypelessFormat[createinfo->format] : SDLToD3D12_DepthFormat[createinfo->format];
}
if (needsUAV) {
@@ -3260,7 +3375,6 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
}
initialState = isSwapchainTexture ? D3D12_RESOURCE_STATE_PRESENT : D3D12_INTERNAL_DefaultTextureResourceState(createinfo->usage);
clearValue.Format = desc.Format;
res = ID3D12Device_CreateCommittedResource(
renderer->device,
@@ -3280,9 +3394,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
texture->resource = handle;
// Create the SRV if applicable
if ((createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) ||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) ||
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) {
if (needsSRV) {
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
D3D12_INTERNAL_AssignStagingDescriptorHandle(
@@ -3483,7 +3595,9 @@ static SDL_GPUTexture *D3D12_CreateTexture(
// Copy properties so we don't lose information when the client destroys them
container->header.info = *createinfo;
container->header.info.props = SDL_CreateProperties();
SDL_CopyProperties(createinfo->props, container->header.info.props);
if (createinfo->props) {
SDL_CopyProperties(createinfo->props, container->header.info.props);
}
container->textureCapacity = 1;
container->textureCount = 1;
@@ -8100,8 +8214,7 @@ static void D3D12_INTERNAL_InitBlitResources(
shaderCreateInfo.code = (Uint8 *)D3D12_FullscreenVert;
shaderCreateInfo.code_size = sizeof(D3D12_FullscreenVert);
shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
shaderCreateInfo.entrypoint = "main";
shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXIL;
renderer->blitVertexShader = D3D12_CreateShader(
(SDL_GPURenderer *)renderer,
@@ -8338,38 +8451,38 @@ static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
}
#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) && defined(HAVE_IDXGIINFOQUEUE)
static void D3D12_INTERNAL_TryInitializeDXGIDebug(D3D12Renderer *renderer)
static bool D3D12_INTERNAL_TryInitializeDXGIDebug(D3D12Renderer *renderer)
{
PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc;
HRESULT res;
renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL);
if (renderer->dxgidebug_dll == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not find " DXGIDEBUG_DLL);
return;
return false;
}
DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction(
renderer->dxgidebug_dll,
DXGI_GET_DEBUG_INTERFACE_FUNC);
if (DXGIGetDebugInterfaceFunc == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC);
return;
return false;
}
res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug);
if (FAILED(res)) {
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIDebug interface");
return false;
}
res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
if (FAILED(res)) {
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIInfoQueue interface");
return false;
}
return true;
}
#endif
static void D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
static bool D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
{
PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterfaceFunc;
HRESULT res;
@@ -8378,21 +8491,20 @@ static void D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
renderer->d3d12_dll,
D3D12_GET_DEBUG_INTERFACE_FUNC);
if (D3D12GetDebugInterfaceFunc == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " D3D12_GET_DEBUG_INTERFACE_FUNC);
return;
return false;
}
res = D3D12GetDebugInterfaceFunc(D3D_GUID(D3D_IID_ID3D12Debug), (void **)&renderer->d3d12Debug);
if (FAILED(res)) {
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get ID3D12Debug interface");
return;
return false;
}
ID3D12Debug_EnableDebugLayer(renderer->d3d12Debug);
return true;
}
#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
static bool D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *renderer)
static void D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *renderer)
{
ID3D12InfoQueue *infoQueue = NULL;
D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
@@ -8404,7 +8516,7 @@ static bool D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *rende
D3D_GUID(D3D_IID_ID3D12InfoQueue),
(void **)&infoQueue);
if (FAILED(res)) {
CHECK_D3D12_ERROR_AND_RETURN("Failed to convert ID3D12Device to ID3D12InfoQueue", false);
return;
}
SDL_zero(filter);
@@ -8420,8 +8532,6 @@ static bool D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *rende
true);
ID3D12InfoQueue_Release(infoQueue);
return true;
}
static void WINAPI D3D12_INTERNAL_OnD3D12DebugInfoMsg(
@@ -8570,9 +8680,12 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
#ifdef HAVE_IDXGIINFOQUEUE
// Initialize the DXGI debug layer, if applicable
bool hasDxgiDebug = false;
if (debugMode) {
D3D12_INTERNAL_TryInitializeDXGIDebug(renderer);
hasDxgiDebug = D3D12_INTERNAL_TryInitializeDXGIDebug(renderer);
}
#else
bool hasDxgiDebug = true;
#endif
// Load the CreateDXGIFactory1 function
@@ -8705,7 +8818,20 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
// Initialize the D3D12 debug layer, if applicable
if (debugMode) {
D3D12_INTERNAL_TryInitializeD3D12Debug(renderer);
bool hasD3d12Debug = D3D12_INTERNAL_TryInitializeD3D12Debug(renderer);
if (hasDxgiDebug && hasD3d12Debug) {
SDL_LogInfo(
SDL_LOG_CATEGORY_GPU,
"Validation layers enabled, expect debug level performance!");
} else if (hasDxgiDebug || hasD3d12Debug) {
SDL_LogWarn(
SDL_LOG_CATEGORY_GPU,
"Validation layers partially enabled, some warnings may not be available");
} else {
SDL_LogWarn(
SDL_LOG_CATEGORY_GPU,
"Validation layers not found, continuing without validation");
}
}
// Create the D3D12Device
@@ -8752,9 +8878,7 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
// Initialize the D3D12 debug info queue, if applicable
if (debugMode) {
if (!D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(renderer)) {
return NULL;
}
D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(renderer);
D3D12_INTERNAL_TryInitializeD3D12DebugInfoLogger(renderer);
}
#endif
+8 -2
View File
@@ -840,6 +840,10 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
dispatch_data_t data;
id<MTLFunction> function;
if (!entrypoint) {
entrypoint = "main0";
}
if (format == SDL_GPU_SHADERFORMAT_MSL) {
NSString *codeString = [[NSString alloc]
initWithBytes:code
@@ -854,7 +858,7 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
code,
codeSize,
dispatch_get_global_queue(0, 0),
^{ /* do nothing */ });
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
library = [renderer->device newLibraryWithData:data error:&error];
} else {
SDL_assert(!"SDL_gpu.c should have already validated this!");
@@ -1494,7 +1498,9 @@ static SDL_GPUTexture *METAL_CreateTexture(
// Copy properties so we don't lose information when the client destroys them
container->header.info = *createinfo;
container->header.info.props = SDL_CreateProperties();
SDL_CopyProperties(createinfo->props, container->header.info.props);
if (createinfo->props) {
SDL_CopyProperties(createinfo->props, container->header.info.props);
}
container->activeTexture = texture;
container->textureCapacity = 1;
+180 -127
View File
@@ -606,7 +606,7 @@ typedef struct VulkanSampler
typedef struct VulkanShader
{
VkShaderModule shaderModule;
const char *entrypointName;
char *entrypointName;
SDL_GPUShaderStage stage;
Uint32 numSamplers;
Uint32 numStorageTextures;
@@ -732,7 +732,7 @@ typedef struct WindowData
// Synchronization primitives
VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
VkSemaphore renderFinishedSemaphore[MAX_FRAMES_IN_FLIGHT];
VkSemaphore *renderFinishedSemaphore;
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
Uint32 frameCounter;
@@ -1135,6 +1135,7 @@ struct VulkanRenderer
VulkanMemoryAllocator *memoryAllocator;
VkPhysicalDeviceMemoryProperties memoryProperties;
bool checkEmptyAllocations;
WindowData **claimedWindows;
Uint32 claimedWindowCount;
@@ -1203,7 +1204,11 @@ struct VulkanRenderer
SDL_Mutex *submitLock;
SDL_Mutex *acquireCommandBufferLock;
SDL_Mutex *acquireUniformBufferLock;
SDL_Mutex *renderPassFetchLock;
SDL_Mutex *framebufferFetchLock;
SDL_Mutex *graphicsPipelineLayoutFetchLock;
SDL_Mutex *computePipelineLayoutFetchLock;
SDL_Mutex *descriptorSetLayoutFetchLock;
SDL_Mutex *windowLock;
Uint8 defragInProgress;
@@ -1221,7 +1226,7 @@ struct VulkanRenderer
// Forward declarations
static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer);
static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
static bool VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
static void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window);
static bool VULKAN_Wait(SDL_GPURenderer *driverData);
@@ -1253,6 +1258,7 @@ static inline const char *VkErrorMessages(VkResult code)
ERR_TO_STR(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
ERR_TO_STR(VK_SUBOPTIMAL_KHR)
ERR_TO_STR(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)
ERR_TO_STR(VK_ERROR_INVALID_SHADER_NV)
default:
return "Unhandled VkResult!";
}
@@ -1577,6 +1583,10 @@ static void VULKAN_INTERNAL_RemoveMemoryUsedRegion(
usedRegion->offset,
usedRegion->size);
if (usedRegion->allocation->usedRegionCount == 0) {
renderer->checkEmptyAllocations = true;
}
SDL_free(usedRegion);
SDL_UnlockMutex(renderer->allocatorLock);
@@ -3169,7 +3179,7 @@ static void VULKAN_INTERNAL_DestroyShader(
vulkanShader->shaderModule,
NULL);
SDL_free((void *)vulkanShader->entrypointName);
SDL_free(vulkanShader->entrypointName);
SDL_free(vulkanShader);
}
@@ -3207,7 +3217,6 @@ static void VULKAN_INTERNAL_DestroySwapchain(
SDL_free(windowData->textureContainers[i].activeTexture->subresources);
SDL_free(windowData->textureContainers[i].activeTexture);
}
windowData->imageCount = 0;
SDL_free(windowData->textureContainers);
windowData->textureContainers = NULL;
@@ -3236,7 +3245,8 @@ static void VULKAN_INTERNAL_DestroySwapchain(
NULL);
windowData->imageAvailableSemaphore[i] = VK_NULL_HANDLE;
}
}
for (i = 0; i < windowData->imageCount; i += 1) {
if (windowData->renderFinishedSemaphore[i]) {
renderer->vkDestroySemaphore(
renderer->logicalDevice,
@@ -3245,6 +3255,10 @@ static void VULKAN_INTERNAL_DestroySwapchain(
windowData->renderFinishedSemaphore[i] = VK_NULL_HANDLE;
}
}
SDL_free(windowData->renderFinishedSemaphore);
windowData->renderFinishedSemaphore = NULL;
windowData->imageCount = 0;
}
static void VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(
@@ -3744,10 +3758,13 @@ static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
key.writeStorageBufferCount = writeStorageBufferCount;
key.uniformBufferCount = uniformBufferCount;
SDL_LockMutex(renderer->descriptorSetLayoutFetchLock);
if (SDL_FindInHashTable(
renderer->descriptorSetLayoutHashTable,
(const void *)&key,
(const void **)&layout)) {
SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
return layout;
}
@@ -3830,7 +3847,10 @@ static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
NULL,
&descriptorSetLayout);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorSetLayout, NULL);
if (vulkanResult != VK_SUCCESS) {
SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorSetLayout, NULL);
}
layout = SDL_malloc(sizeof(DescriptorSetLayout));
layout->descriptorSetLayout = descriptorSetLayout;
@@ -3852,6 +3872,7 @@ static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
(const void *)allocedKey,
(const void *)layout, true);
SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
return layout;
}
@@ -3872,10 +3893,14 @@ static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipeli
key.fragmentStorageTextureCount = fragmentShader->numStorageTextures;
key.fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
key.fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
SDL_LockMutex(renderer->graphicsPipelineLayoutFetchLock);
if (SDL_FindInHashTable(
renderer->graphicsPipelineResourceLayoutHashTable,
(const void *)&key,
(const void **)&pipelineResourceLayout)) {
SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
return pipelineResourceLayout;
}
@@ -3958,6 +3983,7 @@ static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipeli
if (vulkanResult != VK_SUCCESS) {
VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, pipelineResourceLayout);
SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
}
@@ -3969,6 +3995,7 @@ static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipeli
(const void *)allocedKey,
(const void *)pipelineResourceLayout, true);
SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
return pipelineResourceLayout;
}
@@ -3987,10 +4014,13 @@ static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipeline
key.readWriteStorageBufferCount = createinfo->num_readwrite_storage_buffers;
key.uniformBufferCount = createinfo->num_uniform_buffers;
SDL_LockMutex(renderer->computePipelineLayoutFetchLock);
if (SDL_FindInHashTable(
renderer->computePipelineResourceLayoutHashTable,
(const void *)&key,
(const void **)&pipelineResourceLayout)) {
SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
return pipelineResourceLayout;
}
@@ -4059,6 +4089,7 @@ static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipeline
if (vulkanResult != VK_SUCCESS) {
VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, pipelineResourceLayout);
SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
}
@@ -4070,6 +4101,7 @@ static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipeline
(const void *)allocedKey,
(const void *)pipelineResourceLayout, true);
SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
return pipelineResourceLayout;
}
@@ -4784,7 +4816,13 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
}
renderer->vkCreateSemaphore(
windowData->inFlightFences[i] = NULL;
}
windowData->renderFinishedSemaphore = SDL_malloc(
sizeof(VkSemaphore) * windowData->imageCount);
for (i = 0; i < windowData->imageCount; i += 1) {
vulkanResult = renderer->vkCreateSemaphore(
renderer->logicalDevice,
&semaphoreCreateInfo,
NULL,
@@ -4803,8 +4841,6 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
windowData->swapchain = VK_NULL_HANDLE;
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
}
windowData->inFlightFences[i] = NULL;
}
windowData->needsSwapchainRecreate = false;
@@ -4938,7 +4974,11 @@ static void VULKAN_DestroyDevice(
SDL_DestroyMutex(renderer->submitLock);
SDL_DestroyMutex(renderer->acquireCommandBufferLock);
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
SDL_DestroyMutex(renderer->renderPassFetchLock);
SDL_DestroyMutex(renderer->framebufferFetchLock);
SDL_DestroyMutex(renderer->graphicsPipelineLayoutFetchLock);
SDL_DestroyMutex(renderer->computePipelineLayoutFetchLock);
SDL_DestroyMutex(renderer->descriptorSetLayoutFetchLock);
SDL_DestroyMutex(renderer->windowLock);
renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
@@ -5595,6 +5635,7 @@ static void VULKAN_PopDebugGroup(
static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
VulkanRenderer *renderer,
bool transitionToDefaultLayout,
const SDL_GPUTextureCreateInfo *createinfo)
{
VkResult vulkanResult;
@@ -5822,15 +5863,17 @@ static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
&nameInfo);
}
// Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout.
VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
renderer,
barrierCommandBuffer,
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
texture);
VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer);
if (transitionToDefaultLayout) {
// Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout.
VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
renderer,
barrierCommandBuffer,
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
texture);
VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer);
}
return texture;
}
@@ -5880,6 +5923,7 @@ static void VULKAN_INTERNAL_CycleActiveBuffer(
static void VULKAN_INTERNAL_CycleActiveTexture(
VulkanRenderer *renderer,
VulkanCommandBuffer *commandBuffer,
VulkanTextureContainer *container)
{
VulkanTexture *texture;
@@ -5897,8 +5941,15 @@ static void VULKAN_INTERNAL_CycleActiveTexture(
// No texture is available, generate a new one.
texture = VULKAN_INTERNAL_CreateTexture(
renderer,
false,
&container->header.info);
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
texture);
if (!texture) {
return;
}
@@ -5962,6 +6013,7 @@ static VulkanTextureSubresource *VULKAN_INTERNAL_PrepareTextureSubresourceForWri
SDL_GetAtomicInt(&textureContainer->activeTexture->referenceCount) > 0) {
VULKAN_INTERNAL_CycleActiveTexture(
renderer,
commandBuffer,
textureContainer);
textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
@@ -6675,7 +6727,6 @@ static SDL_GPUShader *VULKAN_CreateShader(
VkResult vulkanResult;
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
size_t entryPointNameLength;
vulkanShader = SDL_malloc(sizeof(VulkanShader));
vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
@@ -6695,10 +6746,11 @@ static SDL_GPUShader *VULKAN_CreateShader(
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateShaderModule, NULL);
}
entryPointNameLength = SDL_strlen(createinfo->entrypoint) + 1;
vulkanShader->entrypointName = SDL_malloc(entryPointNameLength);
SDL_utf8strlcpy((char *)vulkanShader->entrypointName, createinfo->entrypoint, entryPointNameLength);
const char *entrypoint = createinfo->entrypoint;
if (!entrypoint) {
entrypoint = "main";
}
vulkanShader->entrypointName = SDL_strdup(entrypoint);
vulkanShader->stage = createinfo->stage;
vulkanShader->numSamplers = createinfo->num_samplers;
vulkanShader->numStorageTextures = createinfo->num_storage_textures;
@@ -6744,6 +6796,7 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
texture = VULKAN_INTERNAL_CreateTexture(
renderer,
true,
createinfo);
if (texture == NULL) {
@@ -6755,7 +6808,9 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
// Copy properties so we don't lose information when the client destroys them
container->header.info = *createinfo;
container->header.info.props = SDL_CreateProperties();
SDL_CopyProperties(createinfo->props, container->header.info.props);
if (createinfo->props) {
SDL_CopyProperties(createinfo->props, container->header.info.props);
}
container->canBeCycled = true;
container->activeTexture = texture;
@@ -6918,7 +6973,7 @@ static void VULKAN_INTERNAL_ReleaseBuffer(
renderer->buffersToDestroy[renderer->buffersToDestroyCount] = vulkanBuffer;
renderer->buffersToDestroyCount += 1;
vulkanBuffer->markedForDestroy = 1;
vulkanBuffer->markedForDestroy = true;
vulkanBuffer->container = NULL;
SDL_UnlockMutex(renderer->disposeLock);
@@ -7085,12 +7140,15 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
key.depthStencilTargetDescription.stencilStoreOp = depthStencilTargetInfo->stencil_store_op;
}
SDL_LockMutex(renderer->renderPassFetchLock);
bool result = SDL_FindInHashTable(
renderer->renderPassHashTable,
(const void *)&key,
(const void **)&renderPassWrapper);
if (result) {
SDL_UnlockMutex(renderer->renderPassFetchLock);
return renderPassWrapper->handle;
}
@@ -7102,6 +7160,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
depthStencilTargetInfo);
if (renderPassHandle == VK_NULL_HANDLE) {
SDL_UnlockMutex(renderer->renderPassFetchLock);
return VK_NULL_HANDLE;
}
@@ -7117,6 +7176,8 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
(const void *)allocedKey,
(const void *)renderPassWrapper, true);
SDL_UnlockMutex(renderer->renderPassFetchLock);
return renderPassHandle;
}
@@ -7185,9 +7246,8 @@ static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
(const void *)&key,
(const void **)&vulkanFramebuffer);
SDL_UnlockMutex(renderer->framebufferFetchLock);
if (findResult) {
SDL_UnlockMutex(renderer->framebufferFetchLock);
return vulkanFramebuffer;
}
@@ -7255,19 +7315,18 @@ static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
FramebufferHashTableKey *allocedKey = SDL_malloc(sizeof(FramebufferHashTableKey));
SDL_memcpy(allocedKey, &key, sizeof(FramebufferHashTableKey));
SDL_LockMutex(renderer->framebufferFetchLock);
SDL_InsertIntoHashTable(
renderer->framebufferHashTable,
(const void *)allocedKey,
(const void *)vulkanFramebuffer, true);
SDL_UnlockMutex(renderer->framebufferFetchLock);
} else {
SDL_free(vulkanFramebuffer);
SDL_UnlockMutex(renderer->framebufferFetchLock);
CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateFramebuffer, NULL);
}
SDL_UnlockMutex(renderer->framebufferFetchLock);
return vulkanFramebuffer;
}
@@ -7932,11 +7991,11 @@ static void VULKAN_BindVertexBuffers(
for (Uint32 i = 0; i < numBindings; i += 1) {
VulkanBuffer *buffer = ((VulkanBufferContainer *)bindings[i].buffer)->activeBuffer;
if (vulkanCommandBuffer->vertexBuffers[i] != buffer->buffer || vulkanCommandBuffer->vertexBufferOffsets[i] != bindings[i].offset) {
if (vulkanCommandBuffer->vertexBuffers[firstSlot + i] != buffer->buffer || vulkanCommandBuffer->vertexBufferOffsets[firstSlot + i] != bindings[i].offset) {
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, buffer);
vulkanCommandBuffer->vertexBuffers[i] = buffer->buffer;
vulkanCommandBuffer->vertexBufferOffsets[i] = bindings[i].offset;
vulkanCommandBuffer->vertexBuffers[firstSlot + i] = buffer->buffer;
vulkanCommandBuffer->vertexBufferOffsets[firstSlot + i] = bindings[i].offset;
vulkanCommandBuffer->needVertexBufferBind = true;
}
}
@@ -8099,7 +8158,7 @@ static void VULKAN_BeginComputePass(
vulkanCommandBuffer,
bufferContainer,
storageBufferBindings[i].cycle,
VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ);
VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = buffer;
@@ -9970,7 +10029,7 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
}
vulkanCommandBuffer->signalSemaphores[vulkanCommandBuffer->signalSemaphoreCount] =
windowData->renderFinishedSemaphore[windowData->frameCounter];
windowData->renderFinishedSemaphore[swapchainImageIndex];
vulkanCommandBuffer->signalSemaphoreCount += 1;
*swapchainTexture = (SDL_GPUTexture *)swapchainTextureContainer;
@@ -10433,9 +10492,10 @@ static bool VULKAN_Submit(
VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT];
Uint32 swapchainImageIndex;
VulkanTextureSubresource *swapchainTextureSubresource;
Uint8 commandBufferCleaned = 0;
VulkanMemorySubAllocator *allocator;
bool presenting = false;
bool performCleanups =
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->presentDataCount > 0) ||
renderer->claimedWindowCount == 0;
SDL_LockMutex(renderer->submitLock);
@@ -10458,6 +10518,15 @@ static bool VULKAN_Submit(
swapchainTextureSubresource);
}
if (performCleanups &&
renderer->allocationsToDefragCount > 0 &&
!renderer->defragInProgress) {
if (!VULKAN_INTERNAL_DefragmentMemory(renderer, vulkanCommandBuffer))
{
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to defragment memory, likely OOM!");
}
}
if (!VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer)) {
SDL_UnlockMutex(renderer->submitLock);
return false;
@@ -10495,17 +10564,13 @@ static bool VULKAN_Submit(
}
// Present, if applicable
bool result = true;
for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
presenting = true;
presentData = &vulkanCommandBuffer->presentDatas[j];
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pNext = NULL;
presentInfo.pWaitSemaphores =
&presentData->windowData->renderFinishedSemaphore[presentData->windowData->frameCounter];
&presentData->windowData->renderFinishedSemaphore[presentData->swapchainImageIndex];
presentInfo.waitSemaphoreCount = 1;
presentInfo.pSwapchains = &presentData->windowData->swapchain;
presentInfo.swapchainCount = 1;
@@ -10537,60 +10602,50 @@ static bool VULKAN_Submit(
(presentData->windowData->frameCounter + 1) % renderer->allowedFramesInFlight;
}
// Check if we can perform any cleanups
if (performCleanups) {
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
vulkanResult = renderer->vkGetFenceStatus(
renderer->logicalDevice,
renderer->submittedCommandBuffers[i]->inFlightFence->fence);
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
vulkanResult = renderer->vkGetFenceStatus(
renderer->logicalDevice,
renderer->submittedCommandBuffers[i]->inFlightFence->fence);
if (vulkanResult == VK_SUCCESS) {
VULKAN_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i],
false);
commandBufferCleaned = 1;
}
}
if (commandBufferCleaned) {
SDL_LockMutex(renderer->allocatorLock);
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
allocator = &renderer->memoryAllocator->subAllocators[i];
for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
if (allocator->allocations[j]->usedRegionCount == 0) {
VULKAN_INTERNAL_DeallocateMemory(
renderer,
allocator,
j);
}
if (vulkanResult == VK_SUCCESS) {
VULKAN_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i],
false);
}
}
SDL_UnlockMutex(renderer->allocatorLock);
}
if (renderer->checkEmptyAllocations) {
SDL_LockMutex(renderer->allocatorLock);
// Check pending destroys
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
allocator = &renderer->memoryAllocator->subAllocators[i];
// Defrag!
if (
presenting &&
renderer->allocationsToDefragCount > 0 &&
!renderer->defragInProgress) {
result = VULKAN_INTERNAL_DefragmentMemory(renderer);
for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
if (allocator->allocations[j]->usedRegionCount == 0) {
VULKAN_INTERNAL_DeallocateMemory(
renderer,
allocator,
j);
}
}
}
renderer->checkEmptyAllocations = false;
SDL_UnlockMutex(renderer->allocatorLock);
}
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
}
// Mark command buffer as submitted
// This must happen after defrag, because it will try to acquire new command buffers.
VULKAN_INTERNAL_ReleaseCommandBuffer(vulkanCommandBuffer);
SDL_UnlockMutex(renderer->submitLock);
return result;
return true;
}
static bool VULKAN_Cancel(
@@ -10617,43 +10672,28 @@ static bool VULKAN_Cancel(
}
static bool VULKAN_INTERNAL_DefragmentMemory(
VulkanRenderer *renderer)
VulkanRenderer *renderer,
VulkanCommandBuffer *commandBuffer)
{
VulkanMemoryAllocation *allocation;
VulkanMemoryUsedRegion *currentRegion;
VulkanBuffer *newBuffer;
VulkanTexture *newTexture;
VkBufferCopy bufferCopy;
VkImageCopy imageCopy;
VulkanCommandBuffer *commandBuffer;
VulkanTextureSubresource *srcSubresource;
VulkanTextureSubresource *dstSubresource;
Uint32 i, subresourceIndex;
renderer->defragInProgress = 1;
commandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
if (commandBuffer == NULL) {
return false;
}
commandBuffer->isDefrag = 1;
SDL_LockMutex(renderer->allocatorLock);
allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
VulkanMemoryAllocation *allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
renderer->allocationsToDefragCount -= 1;
/* For each used region in the allocation
* create a new resource, copy the data
* and re-point the resource containers
*/
for (i = 0; i < allocation->usedRegionCount; i += 1) {
currentRegion = allocation->usedRegions[i];
for (Uint32 i = 0; i < allocation->usedRegionCount; i += 1) {
VulkanMemoryUsedRegion *currentRegion = allocation->usedRegions[i];
if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) {
currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
newBuffer = VULKAN_INTERNAL_CreateBuffer(
VulkanBuffer *newBuffer = VULKAN_INTERNAL_CreateBuffer(
renderer,
currentRegion->vulkanBuffer->size,
currentRegion->vulkanBuffer->usage,
@@ -10663,6 +10703,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
if (newBuffer == NULL) {
SDL_UnlockMutex(renderer->allocatorLock);
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
return false;
}
@@ -10681,6 +10722,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
newBuffer);
VkBufferCopy bufferCopy;
bufferCopy.srcOffset = 0;
bufferCopy.dstOffset = 0;
bufferCopy.size = currentRegion->resourceSize;
@@ -10720,20 +10762,22 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
VULKAN_INTERNAL_ReleaseBuffer(renderer, currentRegion->vulkanBuffer);
} else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
newTexture = VULKAN_INTERNAL_CreateTexture(
VulkanTexture *newTexture = VULKAN_INTERNAL_CreateTexture(
renderer,
false,
&currentRegion->vulkanTexture->container->header.info);
if (newTexture == NULL) {
SDL_UnlockMutex(renderer->allocatorLock);
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
return false;
}
SDL_GPUTextureCreateInfo info = currentRegion->vulkanTexture->container->header.info;
for (subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
for (Uint32 subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
// copy subresource if necessary
srcSubresource = &currentRegion->vulkanTexture->subresources[subresourceIndex];
dstSubresource = &newTexture->subresources[subresourceIndex];
VulkanTextureSubresource *srcSubresource = &currentRegion->vulkanTexture->subresources[subresourceIndex];
VulkanTextureSubresource *dstSubresource = &newTexture->subresources[subresourceIndex];
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
renderer,
@@ -10741,12 +10785,14 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
srcSubresource);
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
dstSubresource);
VkImageCopy imageCopy;
imageCopy.srcOffset.x = 0;
imageCopy.srcOffset.y = 0;
imageCopy.srcOffset.z = 0;
@@ -10798,8 +10844,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
SDL_UnlockMutex(renderer->allocatorLock);
return VULKAN_Submit(
(SDL_GPUCommandBuffer *)commandBuffer);
return true;
}
// Format Info
@@ -11564,7 +11609,7 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
{
// Set up dummy VulkanRenderer
VulkanRenderer *renderer;
Uint8 result;
bool result = false;
if (_this->Vulkan_CreateSurface == NULL) {
return false;
@@ -11574,16 +11619,16 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
return false;
}
renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
result = VULKAN_INTERNAL_PrepareVulkan(renderer);
if (result) {
renderer->vkDestroyInstance(renderer->instance, NULL);
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer) {
result = VULKAN_INTERNAL_PrepareVulkan(renderer);
if (result) {
renderer->vkDestroyInstance(renderer->instance, NULL);
}
SDL_free(renderer);
}
SDL_free(renderer);
SDL_Vulkan_UnloadLibrary();
return result;
}
@@ -11599,8 +11644,12 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
return NULL;
}
renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_Vulkan_UnloadLibrary();
return false;
}
renderer->debugMode = debugMode;
renderer->preferLowPower = preferLowPower;
renderer->allowedFramesInFlight = 2;
@@ -11661,7 +11710,11 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->submitLock = SDL_CreateMutex();
renderer->acquireCommandBufferLock = SDL_CreateMutex();
renderer->acquireUniformBufferLock = SDL_CreateMutex();
renderer->renderPassFetchLock = SDL_CreateMutex();
renderer->framebufferFetchLock = SDL_CreateMutex();
renderer->graphicsPipelineLayoutFetchLock = SDL_CreateMutex();
renderer->computePipelineLayoutFetchLock = SDL_CreateMutex();
renderer->descriptorSetLayoutFetchLock = SDL_CreateMutex();
renderer->windowLock = SDL_CreateMutex();
/*
@@ -11722,7 +11775,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->renderPassHashTable = SDL_CreateHashTable(
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
true, // thread-safe
false, // manually synchronized due to lookup timing
VULKAN_INTERNAL_RenderPassHashFunction,
VULKAN_INTERNAL_RenderPassHashKeyMatch,
VULKAN_INTERNAL_RenderPassHashDestroy,
@@ -11738,7 +11791,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->graphicsPipelineResourceLayoutHashTable = SDL_CreateHashTable(
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
true, // thread-safe
false, // manually synchronized due to lookup timing
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction,
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch,
VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashDestroy,
@@ -11746,7 +11799,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->computePipelineResourceLayoutHashTable = SDL_CreateHashTable(
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
true, // thread-safe
false, // manually synchronized due to lookup timing
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction,
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch,
VULKAN_INTERNAL_ComputePipelineResourceLayoutHashDestroy,
@@ -11754,7 +11807,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->descriptorSetLayoutHashTable = SDL_CreateHashTable(
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
true, // thread-safe
false, // manually synchronized due to lookup timing
VULKAN_INTERNAL_DescriptorSetLayoutHashFunction,
VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch,
VULKAN_INTERNAL_DescriptorSetLayoutHashDestroy,
+2
View File
@@ -807,6 +807,8 @@ typedef struct LIBUSB_hid_device_ LIBUSB_hid_device;
#define hid_send_feature_report LIBUSB_hid_send_feature_report
#define hid_set_nonblocking LIBUSB_hid_set_nonblocking
#define hid_write LIBUSB_hid_write
#define hid_version LIBUSB_hid_version
#define hid_version_str LIBUSB_hid_version_str
#define input_report LIBUSB_input_report
#define make_path LIBUSB_make_path
#define new_hid_device LIBUSB_new_hid_device
+4
View File
@@ -62,6 +62,10 @@
#define wcsstr SDL_wcsstr
#define wcstol SDL_wcstol
// These functions conflict when linking both SDL and hidapi statically
#define hid_winapi_descriptor_reconstruct_pp_data SDL_hid_winapi_descriptor_reconstruct_pp_data
#define hid_winapi_get_container_id SDL_hid_winapi_get_container_id
#undef HIDAPI_H__
#include "windows/hid.c"
#define HAVE_PLATFORM_BACKEND 1
+1
View File
@@ -1238,6 +1238,7 @@ static void init_xbox360(libusb_device_handle *device_handle, unsigned short idV
(void)conf_desc;
if ((idVendor == 0x05ac && idProduct == 0x055b) /* Gamesir-G3w */ ||
(idVendor == 0x20d6 && idProduct == 0x4010) /* PowerA Battle Dragon Advanced Wireless Controller */ ||
idVendor == 0x0f0d /* Hori Xbox controllers */) {
unsigned char data[20];
+3 -2
View File
@@ -309,12 +309,13 @@ bool SDL_LoadFileAsync(const char *file, SDL_AsyncIOQueue *queue, void *userdata
if (asyncio) {
asyncio->oneshot = true;
void *ptr = NULL;
Uint8 *ptr = NULL;
const Sint64 flen = SDL_GetAsyncIOSize(asyncio);
if (flen >= 0) {
// !!! FIXME: check if flen > address space, since it'll truncate and we'll just end up with an incomplete buffer or a crash.
ptr = SDL_malloc((size_t) (flen + 1)); // over-allocate by one so we can add a null-terminator.
ptr = (Uint8 *) SDL_malloc((size_t) (flen + 1)); // over-allocate by one so we can add a null-terminator.
if (ptr) {
ptr[flen] = '\0';
retval = SDL_ReadAsyncIO(asyncio, ptr, 0, (Uint64) flen, queue, userdata);
if (!retval) {
SDL_free(ptr);
+21 -16
View File
@@ -405,15 +405,17 @@ static bool SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
{
SDL_AssertJoysticksLocked();
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
if (gamepad->joystick->instance_id == event->jdevice.which) {
SDL_Event deviceevent;
if (SDL_EventEnabled(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE)) {
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
if (gamepad->joystick->instance_id == event->jdevice.which) {
SDL_Event deviceevent;
deviceevent.type = SDL_EVENT_GAMEPAD_UPDATE_COMPLETE;
deviceevent.common.timestamp = event->jdevice.timestamp;
deviceevent.gdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);
break;
deviceevent.type = SDL_EVENT_GAMEPAD_UPDATE_COMPLETE;
deviceevent.common.timestamp = event->jdevice.timestamp;
deviceevent.gdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);
break;
}
}
}
} break;
@@ -729,7 +731,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string));
break;
case k_eSwitchDeviceInfoControllerType_SNES:
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,", sizeof(mapping_string));
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
break;
case k_eSwitchDeviceInfoControllerType_N64:
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,misc1:b11,", sizeof(mapping_string));
@@ -773,13 +775,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
// All other gamepads have the standard set of 19 buttons and 6 axes
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string));
if (SDL_IsJoystickXboxSeriesX(vendor, product)) {
// XBox Series X Controllers have a share button under the guide button
SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string));
} else if (SDL_IsJoystickXboxOneElite(vendor, product)) {
// XBox One Elite Controllers have 4 back paddle buttons
SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,", sizeof(mapping_string));
} else if (SDL_IsJoystickSteamController(vendor, product)) {
if (SDL_IsJoystickSteamController(vendor, product)) {
// Steam controllers have 2 back paddle buttons
SDL_strlcat(mapping_string, "paddle1:b12,paddle2:b11,", sizeof(mapping_string));
} else if (SDL_IsJoystickNintendoSwitchPro(vendor, product) ||
@@ -820,6 +816,15 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
SDL_strlcat(mapping_string, "paddle1:b16,paddle2:b15,paddle3:b14,paddle4:b13,", sizeof(mapping_string));
}
break;
case SDL_GAMEPAD_TYPE_XBOXONE:
if (SDL_IsJoystickXboxOneElite(vendor, product)) {
// XBox One Elite Controllers have 4 back paddle buttons
SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,", sizeof(mapping_string));
} else if (SDL_IsJoystickXboxSeriesX(vendor, product)) {
// XBox Series X Controllers have a share button under the guide button
SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string));
}
break;
default:
if (vendor == 0 && product == 0) {
// This is a Bluetooth Nintendo Switch Pro controller
+12 -3
View File
@@ -215,7 +215,7 @@ static const char *s_GamepadMappings[] = {
"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,",
"03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,",
"030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,",
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,start:b11,x:b3,y:b4,",
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:-a5,start:b11,x:b3,y:b4,",
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,",
"030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
@@ -421,7 +421,7 @@ static const char *s_GamepadMappings[] = {
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,start:b11,x:b3,y:b4,",
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:a5,start:b11,x:b3,y:b4,",
"030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
@@ -553,6 +553,7 @@ static const char *s_GamepadMappings[] = {
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
"03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"0500000049190000020400001b010000,GameSir T4 Pro,crc:8283,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b23,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"03000000373500009710000001020000,GameSir-K1 FLUX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"03000000c01100000140000011010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
@@ -641,6 +642,12 @@ static const char *s_GamepadMappings[] = {
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000790000004318000010010000,Nintendo GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000007e0500001920000011810000,Nintendo N64 Controller,crc:d670,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b3,start:b11,x:b4,y:b10,",
"050000007e0500001920000001800000,Nintendo N64 Controller,crc:5e1c,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b3,start:b11,x:b4,y:b10,",
"030000007e0500001e20000011810000,Nintendo SEGA Genesis Controller,crc:bb22,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,",
"050000007e0500001720000001800000,Nintendo SEGA Genesis Controller,crc:c1bf,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,",
"030000007e0500001720000011810000,Nintendo SNES Controller,crc:f648,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500001720000001800000,Nintendo SNES Controller,crc:dbc0,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000620000001800000,Nintendo Switch Joy-Con (L),a:b16,b:b15,guide:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"060000007e0500000620000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"060000007e0500000820000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
@@ -861,7 +868,9 @@ static const char *s_GamepadMappings[] = {
"05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
"05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,",
"05000000ac05000004000000a8986d04,8BitDo Micro gamepad,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000ac05000004000000fd216d04,8BitDo Pro 2,crc:ac95,a:b3,b:b2,back:b6,dpdown:b9,dpleft:b10,dpright:b11,dpup:b12,guide:b4,leftshoulder:b13,leftstick:b14,lefttrigger:+a2,leftx:a0,lefty:a1~,paddle1:b1,paddle2:b0,rightshoulder:b16,rightstick:b17,righttrigger:+a5,rightx:a3,righty:a4~,start:b5,x:b8,y:b7,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,crc:3e00,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000ac05000004000000209f6d04,8Bitdo SN30 Pro,crc:40d6,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
"050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
"050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
@@ -898,7 +907,7 @@ static const char *s_GamepadMappings[] = {
"0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
#endif
#ifdef SDL_JOYSTICK_N3DS
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b0,b:b1,back:b2,dpdown:b7,dpleft:b5,dpright:b4,dpup:b6,leftshoulder:b9,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b15,rightx:a2,righty:a3,start:b3,x:b10,y:b11,",
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b1,b:b0,back:b2,dpdown:b7,dpleft:b5,dpright:b4,dpup:b6,leftshoulder:b9,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b15,rightx:a2,righty:a3,start:b3,x:b11,y:b10,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
#endif
NULL
};
+101 -1
View File
@@ -277,6 +277,7 @@ static Uint32 initial_blacklist_devices[] = {
MAKE_VIDPID(0x1532, 0x0282), // Razer Huntsman Mini Analog, non-functional DInput device
MAKE_VIDPID(0x26ce, 0x01a2), // ASRock LED Controller
MAKE_VIDPID(0x20d6, 0x0002), // PowerA Enhanced Wireless Controller for Nintendo Switch (charging port only)
MAKE_VIDPID(0x3434, 0x0211), // Keychron K1 Pro System Control
};
static SDL_vidpid_list blacklist_devices = {
SDL_HINT_JOYSTICK_BLACKLIST_DEVICES, 0, 0, NULL,
@@ -289,7 +290,17 @@ static Uint32 initial_flightstick_devices[] = {
MAKE_VIDPID(0x044f, 0x0402), // HOTAS Warthog Joystick
MAKE_VIDPID(0x044f, 0xb10a), // ThrustMaster, Inc. T.16000M Joystick
MAKE_VIDPID(0x046d, 0xc215), // Logitech Extreme 3D
MAKE_VIDPID(0x0583, 0x6258), // Padix USB joystick with viewfinder
MAKE_VIDPID(0x0583, 0x688f), // Padix QF-688uv Windstorm Pro
MAKE_VIDPID(0x0583, 0x7070), // Padix QF-707u Bazooka
MAKE_VIDPID(0x0583, 0xa019), // Padix USB vibration joystick with viewfinder
MAKE_VIDPID(0x0583, 0xa131), // Padix USB Wireless 2.4GHz
MAKE_VIDPID(0x0583, 0xa209), // Padix MetalStrike ForceFeedback
MAKE_VIDPID(0x0583, 0xb010), // Padix MetalStrike Pro
MAKE_VIDPID(0x0583, 0xb012), // Padix Wireless MetalStrike
MAKE_VIDPID(0x0583, 0xb013), // Padix USB Wireless 2.4GHZ
MAKE_VIDPID(0x0738, 0x2221), // Saitek Pro Flight X-56 Rhino Stick
MAKE_VIDPID(0x10f5, 0x7084), // Turtle Beach VelocityOne
MAKE_VIDPID(0x231d, 0x0126), // Gunfighter Mk.III 'Space Combat Edition' (right)
MAKE_VIDPID(0x231d, 0x0127), // Gunfighter Mk.III 'Space Combat Edition' (left)
MAKE_VIDPID(0x362c, 0x0001), // Yawman Arrow
@@ -331,6 +342,7 @@ static SDL_vidpid_list rog_gamepad_mice = {
static Uint32 initial_throttle_devices[] = {
MAKE_VIDPID(0x044f, 0x0404), // HOTAS Warthog Throttle
MAKE_VIDPID(0x0738, 0xa221), // Saitek Pro Flight X-56 Rhino Throttle
MAKE_VIDPID(0x10f5, 0x7085), // Turtle Beach VelocityOne Throttle
};
static SDL_vidpid_list throttle_devices = {
SDL_HINT_JOYSTICK_THROTTLE_DEVICES, 0, 0, NULL,
@@ -374,6 +386,14 @@ static Uint32 initial_wheel_devices[] = {
MAKE_VIDPID(0x046d, 0xca03), // Logitech Momo Racing
MAKE_VIDPID(0x0483, 0x0522), // Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U)
MAKE_VIDPID(0x0483, 0xa355), // VRS DirectForce Pro Wheel Base
MAKE_VIDPID(0x0583, 0xa132), // Padix USB Wireless 2.4GHz Wheelpad
MAKE_VIDPID(0x0583, 0xa133), // Padix USB Wireless 2.4GHz Wheel
MAKE_VIDPID(0x0583, 0xa202), // Padix Force Feedback Wheel
MAKE_VIDPID(0x0583, 0xb002), // Padix Vibration USB Wheel
MAKE_VIDPID(0x0583, 0xb005), // Padix USB Wheel
MAKE_VIDPID(0x0583, 0xb008), // Padix USB Wireless 2.4GHz Wheel
MAKE_VIDPID(0x0583, 0xb009), // Padix USB Wheel
MAKE_VIDPID(0x0583, 0xb018), // Padix TW6 Wheel
MAKE_VIDPID(0x0eb7, 0x0001), // Fanatec ClubSport Wheel Base V2
MAKE_VIDPID(0x0eb7, 0x0004), // Fanatec ClubSport Wheel Base V2.5
MAKE_VIDPID(0x0eb7, 0x0005), // Fanatec CSL Elite Wheel Base+ (PS4)
@@ -427,6 +447,13 @@ static SDL_vidpid_list zero_centered_devices = {
return result; \
}
#define CHECK_JOYSTICK_VIRTUAL(joystick, result) \
if (!joystick->is_virtual) { \
SDL_SetError("joystick isn't virtual"); \
SDL_UnlockJoysticks(); \
return result; \
}
bool SDL_JoysticksInitialized(void)
{
return SDL_joysticks_initialized;
@@ -1043,6 +1070,27 @@ static void CleanupSensorFusion(SDL_Joystick *joystick)
}
}
static bool ShouldSwapFaceButtons(const SDL_SteamVirtualGamepadInfo *info)
{
// When "Use Nintendo Button Layout" is enabled under Steam (the default)
// it will send button 0 for the A (east) button and button 1 for the
// B (south) button. This is done so that games that interpret the
// buttons as Xbox input will get button 0 for "A" as they expect.
//
// However, SDL reports positional buttons, so we need to swap
// the buttons so they show up in the correct position. This provides
// consistent behavior regardless of whether we're running under Steam,
// under the default settings.
if (info &&
(info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR)) {
return true;
}
return false;
}
/*
* Open a joystick for use - the index passed as an argument refers to
* the N'th joystick on the system. This index is the value which will
@@ -1094,6 +1142,11 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
joystick->attached = true;
joystick->led_expiration = SDL_GetTicks();
joystick->battery_percent = -1;
#ifdef SDL_JOYSTICK_VIRTUAL
joystick->is_virtual = (driver == &SDL_VIRTUAL_JoystickDriver);
#else
joystick->is_virtual = false;
#endif
if (!driver->Open(joystick, device_index)) {
SDL_SetObjectValid(joystick, SDL_OBJECT_TYPE_JOYSTICK, false);
@@ -1148,6 +1201,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id);
if (info) {
joystick->steam_handle = info->handle;
joystick->swap_face_buttons = ShouldSwapFaceButtons(info);
}
// Use system gyro and accelerometer if the gamepad doesn't have built-in sensors
@@ -1225,6 +1279,7 @@ bool SDL_SetJoystickVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value)
SDL_LockJoysticks();
{
CHECK_JOYSTICK_MAGIC(joystick, false);
CHECK_JOYSTICK_VIRTUAL(joystick, false);
#ifdef SDL_JOYSTICK_VIRTUAL
result = SDL_SetJoystickVirtualAxisInner(joystick, axis, value);
@@ -1244,6 +1299,7 @@ bool SDL_SetJoystickVirtualBall(SDL_Joystick *joystick, int ball, Sint16 xrel, S
SDL_LockJoysticks();
{
CHECK_JOYSTICK_MAGIC(joystick, false);
CHECK_JOYSTICK_VIRTUAL(joystick, false);
#ifdef SDL_JOYSTICK_VIRTUAL
result = SDL_SetJoystickVirtualBallInner(joystick, ball, xrel, yrel);
@@ -1263,6 +1319,7 @@ bool SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, int button, bool down)
SDL_LockJoysticks();
{
CHECK_JOYSTICK_MAGIC(joystick, false);
CHECK_JOYSTICK_VIRTUAL(joystick, false);
#ifdef SDL_JOYSTICK_VIRTUAL
result = SDL_SetJoystickVirtualButtonInner(joystick, button, down);
@@ -1282,6 +1339,7 @@ bool SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value)
SDL_LockJoysticks();
{
CHECK_JOYSTICK_MAGIC(joystick, false);
CHECK_JOYSTICK_VIRTUAL(joystick, false);
#ifdef SDL_JOYSTICK_VIRTUAL
result = SDL_SetJoystickVirtualHatInner(joystick, hat, value);
@@ -1301,6 +1359,7 @@ bool SDL_SetJoystickVirtualTouchpad(SDL_Joystick *joystick, int touchpad, int fi
SDL_LockJoysticks();
{
CHECK_JOYSTICK_MAGIC(joystick, false);
CHECK_JOYSTICK_VIRTUAL(joystick, false);
#ifdef SDL_JOYSTICK_VIRTUAL
result = SDL_SetJoystickVirtualTouchpadInner(joystick, touchpad, finger, down, x, y, pressure);
@@ -1320,6 +1379,7 @@ bool SDL_SendJoystickVirtualSensorData(SDL_Joystick *joystick, SDL_SensorType ty
SDL_LockJoysticks();
{
CHECK_JOYSTICK_MAGIC(joystick, false);
CHECK_JOYSTICK_VIRTUAL(joystick, false);
#ifdef SDL_JOYSTICK_VIRTUAL
result = SDL_SendJoystickVirtualSensorDataInner(joystick, type, sensor_timestamp, data, num_values);
@@ -1778,6 +1838,14 @@ bool SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
result = true;
} else {
result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble);
if (result) {
joystick->trigger_rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS;
if (joystick->trigger_rumble_resend == 0) {
joystick->trigger_rumble_resend = 1;
}
} else {
joystick->trigger_rumble_resend = 0;
}
}
if (result) {
@@ -1788,6 +1856,7 @@ bool SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
} else {
joystick->trigger_rumble_expiration = 0;
joystick->trigger_rumble_resend = 0;
}
}
}
@@ -2305,6 +2374,25 @@ void SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butt
event.type = SDL_EVENT_JOYSTICK_BUTTON_UP;
}
if (joystick->swap_face_buttons) {
switch (button) {
case 0:
button = 1;
break;
case 1:
button = 0;
break;
case 2:
button = 3;
break;
case 3:
button = 2;
break;
default:
break;
}
}
// Make sure we're not getting garbage or duplicate events
if (button >= joystick->nbuttons) {
return;
@@ -2353,11 +2441,13 @@ static void SendSteamHandleUpdateEvents(void)
if (info) {
if (joystick->steam_handle != info->handle) {
joystick->steam_handle = info->handle;
joystick->swap_face_buttons = ShouldSwapFaceButtons(info);
changed = true;
}
} else {
if (joystick->steam_handle != 0) {
joystick->steam_handle = 0;
joystick->swap_face_buttons = false;
changed = true;
}
}
@@ -2421,6 +2511,15 @@ void SDL_UpdateJoysticks(void)
if (joystick->trigger_rumble_expiration && now >= joystick->trigger_rumble_expiration) {
SDL_RumbleJoystickTriggers(joystick, 0, 0, 0);
joystick->trigger_rumble_resend = 0;
}
if (joystick->trigger_rumble_resend && now >= joystick->trigger_rumble_resend) {
joystick->driver->RumbleTriggers(joystick, joystick->left_trigger_rumble, joystick->right_trigger_rumble);
joystick->trigger_rumble_resend = now + SDL_RUMBLE_RESEND_MS;
if (joystick->trigger_rumble_resend == 0) {
joystick->trigger_rumble_resend = 1;
}
}
}
@@ -2801,7 +2900,8 @@ bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id)
}
if (vendor_id == USB_VENDOR_HORI) {
if (product_id == USB_PRODUCT_HORI_FIGHTING_COMMANDER_OCTA_SERIES_X ||
product_id == USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X) {
product_id == USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X ||
product_id == USB_PRODUCT_HORI_TAIKO_DRUM_CONTROLLER) {
return true;
}
}
+3
View File
@@ -83,6 +83,8 @@ struct SDL_Joystick
SDL_GUID guid _guarded; // Joystick guid
Uint16 firmware_version _guarded; // Firmware version, if available
Uint64 steam_handle _guarded; // Steam controller API handle
bool swap_face_buttons _guarded; // Whether we should swap face buttons
bool is_virtual _guarded; // Whether this is a virtual joystick
int naxes _guarded; // Number of axis controls on the joystick
SDL_JoystickAxisInfo *axes _guarded;
@@ -111,6 +113,7 @@ struct SDL_Joystick
Uint16 left_trigger_rumble _guarded;
Uint16 right_trigger_rumble _guarded;
Uint64 trigger_rumble_expiration _guarded;
Uint64 trigger_rumble_resend _guarded;
Uint8 led_red _guarded;
Uint8 led_green _guarded;
+2 -4
View File
@@ -868,10 +868,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
return NULL;
}
SDL_SetObjectValid(device, SDL_OBJECT_TYPE_HIDAPI_JOYSTICK, true);
device->path = SDL_strdup(info->path);
if (!device->path) {
SDL_free(device);
return NULL;
if (info->path) {
device->path = SDL_strdup(info->path);
}
device->seen = true;
device->vendor_id = info->vendor_id;
+1
View File
@@ -76,6 +76,7 @@
#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_HORI_TAIKO_DRUM_CONTROLLER 0x01b2
#define USB_PRODUCT_LOGITECH_F310 0xc216
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
#define USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK 0x2218
+14 -10
View File
@@ -158,8 +158,11 @@ struct joystick_hwdata
Uint8 wgi_correlation_count;
Uint8 wgi_uncorrelate_count;
WindowsGamingInputGamepadState *wgi_slot;
struct __x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration;
#endif
bool triggers_rumbling;
SDL_RAWINPUT_Device *device;
};
typedef struct joystick_hwdata RAWINPUT_DeviceContext;
@@ -447,7 +450,6 @@ typedef struct WindowsGamingInputGamepadState
bool used; // Is currently mapped to an SDL device
bool connected; // Just used during update to track disconnected
Uint8 correlation_id;
struct __x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration;
} WindowsGamingInputGamepadState;
static struct
@@ -909,9 +911,11 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
char *product_string = NULL;
WCHAR string[128];
string[0] = 0;
if (SDL_HidD_GetManufacturerString(hFile, string, sizeof(string))) {
manufacturer_string = WIN_StringToUTF8W(string);
}
string[0] = 0;
if (SDL_HidD_GetProductString(hFile, string, sizeof(string))) {
product_string = WIN_StringToUTF8W(string);
}
@@ -1459,7 +1463,7 @@ static bool RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
// Prefer XInput over WGI because it allows rumble in the background
if (!rumbled && ctx->xinput_correlated) {
if (!rumbled && ctx->xinput_correlated && !ctx->triggers_rumbling) {
XINPUT_VIBRATION XVibration;
if (!XINPUTSETSTATE) {
@@ -1477,12 +1481,12 @@ static bool RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
#endif // SDL_JOYSTICK_RAWINPUT_XINPUT
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
// Save off the motor state in case trigger rumble is started
ctx->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
ctx->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
if (!rumbled && ctx->wgi_correlated) {
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
HRESULT hr;
gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
gamepad_state->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, ctx->vibration);
if (SUCCEEDED(hr)) {
rumbled = true;
}
@@ -1504,15 +1508,15 @@ static bool RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
ctx->vibration.LeftTrigger = (DOUBLE)left_rumble / SDL_MAX_UINT16;
ctx->vibration.RightTrigger = (DOUBLE)right_rumble / SDL_MAX_UINT16;
if (ctx->wgi_correlated) {
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
HRESULT hr;
gamepad_state->vibration.LeftTrigger = (DOUBLE)left_rumble / SDL_MAX_UINT16;
gamepad_state->vibration.RightTrigger = (DOUBLE)right_rumble / SDL_MAX_UINT16;
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, ctx->vibration);
if (!SUCCEEDED(hr)) {
return SDL_SetError("Setting vibration failed: 0x%lx", hr);
}
ctx->triggers_rumbling = (left_rumble > 0 || right_rumble > 0);
return true;
} else {
return SDL_SetError("Controller isn't correlated yet, try hitting a button first");
+4 -3
View File
@@ -304,6 +304,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
if (stderr_option == SDL_PROCESS_STDIO_INHERITED) {
stderr_option = SDL_PROCESS_STDIO_NULL;
}
creation_flags |= CREATE_NO_WINDOW;
}
switch (stdin_option) {
@@ -329,7 +330,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
startup_info.hStdInput = stdin_pipe[READ_END];
break;
case SDL_PROCESS_STDIO_NULL:
startup_info.hStdInput = CreateFile(TEXT("\\\\.\\NUL"), GENERIC_ALL, 0, &security_attributes, OPEN_EXISTING, 0, NULL);
startup_info.hStdInput = CreateFile(TEXT("\\\\.\\NUL"), (GENERIC_READ | GENERIC_WRITE), 0, &security_attributes, OPEN_EXISTING, 0, NULL);
break;
case SDL_PROCESS_STDIO_INHERITED:
default:
@@ -366,7 +367,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
startup_info.hStdOutput = stdout_pipe[WRITE_END];
break;
case SDL_PROCESS_STDIO_NULL:
startup_info.hStdOutput = CreateFile(TEXT("\\\\.\\NUL"), GENERIC_ALL, 0, &security_attributes, OPEN_EXISTING, 0, NULL);
startup_info.hStdOutput = CreateFile(TEXT("\\\\.\\NUL"), (GENERIC_READ | GENERIC_WRITE), 0, &security_attributes, OPEN_EXISTING, 0, NULL);
break;
case SDL_PROCESS_STDIO_INHERITED:
default:
@@ -412,7 +413,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
startup_info.hStdError = stderr_pipe[WRITE_END];
break;
case SDL_PROCESS_STDIO_NULL:
startup_info.hStdError = CreateFile(TEXT("\\\\.\\NUL"), GENERIC_ALL, 0, &security_attributes, OPEN_EXISTING, 0, NULL);
startup_info.hStdError = CreateFile(TEXT("\\\\.\\NUL"), (GENERIC_READ | GENERIC_WRITE), 0, &security_attributes, OPEN_EXISTING, 0, NULL);
break;
case SDL_PROCESS_STDIO_INHERITED:
default:
+91 -100
View File
@@ -213,93 +213,91 @@ static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd)
SDL_Log("Render commands to flush:");
while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_NO_OP:
SDL_Log(" %u. no-op", i++);
break;
case SDL_RENDERCMD_NO_OP:
SDL_Log(" %u. no-op", i++);
break;
case SDL_RENDERCMD_SETVIEWPORT:
SDL_Log(" %u. set viewport (first=%u, rect={(%d, %d), %dx%d})", i++,
(unsigned int) cmd->data.viewport.first,
cmd->data.viewport.rect.x, cmd->data.viewport.rect.y,
cmd->data.viewport.rect.w, cmd->data.viewport.rect.h);
break;
case SDL_RENDERCMD_SETVIEWPORT:
SDL_Log(" %u. set viewport (first=%u, rect={(%d, %d), %dx%d})", i++,
(unsigned int)cmd->data.viewport.first,
cmd->data.viewport.rect.x, cmd->data.viewport.rect.y,
cmd->data.viewport.rect.w, cmd->data.viewport.rect.h);
break;
case SDL_RENDERCMD_SETCLIPRECT:
SDL_Log(" %u. set cliprect (enabled=%s, rect={(%d, %d), %dx%d})", i++,
cmd->data.cliprect.enabled ? "true" : "false",
cmd->data.cliprect.rect.x, cmd->data.cliprect.rect.y,
cmd->data.cliprect.rect.w, cmd->data.cliprect.rect.h);
break;
case SDL_RENDERCMD_SETCLIPRECT:
SDL_Log(" %u. set cliprect (enabled=%s, rect={(%d, %d), %dx%d})", i++,
cmd->data.cliprect.enabled ? "true" : "false",
cmd->data.cliprect.rect.x, cmd->data.cliprect.rect.y,
cmd->data.cliprect.rect.w, cmd->data.cliprect.rect.h);
break;
case SDL_RENDERCMD_SETDRAWCOLOR:
SDL_Log(" %u. set draw color (first=%u, r=%d, g=%d, b=%d, a=%d, color_scale=%g)", i++,
(unsigned int) cmd->data.color.first,
(int) cmd->data.color.color.r, (int) cmd->data.color.color.g,
(int) cmd->data.color.color.b, (int) cmd->data.color.color.a, cmd->data.color.color_scale);
break;
case SDL_RENDERCMD_SETDRAWCOLOR:
SDL_Log(" %u. set draw color (first=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, color_scale=%g)", i++,
(unsigned int)cmd->data.color.first,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a, cmd->data.color.color_scale);
break;
case SDL_RENDERCMD_CLEAR:
SDL_Log(" %u. clear (first=%u, r=%d, g=%d, b=%d, a=%d, color_scale=%g)", i++,
(unsigned int) cmd->data.color.first,
(int) cmd->data.color.color.r, (int) cmd->data.color.color.g,
(int) cmd->data.color.color.b, (int) cmd->data.color.color.a, cmd->data.color.color_scale);
break;
case SDL_RENDERCMD_CLEAR:
SDL_Log(" %u. clear (first=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, color_scale=%g)", i++,
(unsigned int)cmd->data.color.first,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a, cmd->data.color.color_scale);
break;
case SDL_RENDERCMD_DRAW_POINTS:
SDL_Log(" %u. draw points (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
(int) cmd->data.draw.blend, cmd->data.draw.color_scale);
break;
case SDL_RENDERCMD_DRAW_POINTS:
SDL_Log(" %u. draw points (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g)", i++,
(unsigned int)cmd->data.draw.first,
(unsigned int)cmd->data.draw.count,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a,
(int)cmd->data.draw.blend, cmd->data.draw.color_scale);
break;
case SDL_RENDERCMD_DRAW_LINES:
SDL_Log(" %u. draw lines (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
(int) cmd->data.draw.blend, cmd->data.draw.color_scale);
break;
case SDL_RENDERCMD_DRAW_LINES:
SDL_Log(" %u. draw lines (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g)", i++,
(unsigned int)cmd->data.draw.first,
(unsigned int)cmd->data.draw.count,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a,
(int)cmd->data.draw.blend, cmd->data.draw.color_scale);
break;
case SDL_RENDERCMD_FILL_RECTS:
SDL_Log(" %u. fill rects (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
(int) cmd->data.draw.blend, cmd->data.draw.color_scale);
break;
case SDL_RENDERCMD_FILL_RECTS:
SDL_Log(" %u. fill rects (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g)", i++,
(unsigned int)cmd->data.draw.first,
(unsigned int)cmd->data.draw.count,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a,
(int)cmd->data.draw.blend, cmd->data.draw.color_scale);
break;
case SDL_RENDERCMD_COPY:
SDL_Log(" %u. copy (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
(int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
break;
case SDL_RENDERCMD_COPY:
SDL_Log(" %u. copy (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g, tex=%p)", i++,
(unsigned int)cmd->data.draw.first,
(unsigned int)cmd->data.draw.count,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a,
(int)cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
break;
case SDL_RENDERCMD_COPY_EX:
SDL_Log(" %u. copyex (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g, tex=%p)", i++,
(unsigned int)cmd->data.draw.first,
(unsigned int)cmd->data.draw.count,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a,
(int)cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
break;
case SDL_RENDERCMD_COPY_EX:
SDL_Log(" %u. copyex (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
(int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
break;
case SDL_RENDERCMD_GEOMETRY:
SDL_Log(" %u. geometry (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++,
(unsigned int) cmd->data.draw.first,
(unsigned int) cmd->data.draw.count,
(int) cmd->data.draw.color.r, (int) cmd->data.draw.color.g,
(int) cmd->data.draw.color.b, (int) cmd->data.draw.color.a,
(int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
break;
case SDL_RENDERCMD_GEOMETRY:
SDL_Log(" %u. geometry (first=%u, count=%u, r=%.2f, g=%.2f, b=%.2f, a=%.2f, blend=%d, color_scale=%g, tex=%p)", i++,
(unsigned int)cmd->data.draw.first,
(unsigned int)cmd->data.draw.count,
cmd->data.draw.color.r, cmd->data.draw.color.g,
cmd->data.draw.color.b, cmd->data.draw.color.a,
(int)cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture);
break;
}
cmd = cmd->next;
}
@@ -573,6 +571,9 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
cmd->data.draw.color = *color;
cmd->data.draw.blend = blendMode;
cmd->data.draw.texture = texture;
if (texture) {
cmd->data.draw.texture_scale_mode = texture->scaleMode;
}
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
}
}
@@ -827,6 +828,10 @@ static bool SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_Renderer *renderer = (SDL_Renderer *)userdata;
SDL_Window *window = renderer->window;
if (event->window.windowID != SDL_GetWindowID(window)) {
return true;
}
if (renderer->WindowEvent) {
renderer->WindowEvent(renderer, &event->window);
}
@@ -1119,12 +1124,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
}
int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
if (!SDL_SetRenderVSync(renderer, vsync)) {
if (vsync == 0) {
// Some renderers require vsync enabled
SDL_SetRenderVSync(renderer, 1);
}
}
SDL_SetRenderVSync(renderer, vsync);
SDL_CalculateSimulatedVSyncInterval(renderer, window);
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
@@ -1658,8 +1658,6 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
}
}
surface_colorspace = SDL_GetSurfaceColorspace(surface);
// Try to have the best pixel format for the texture
// No alpha, but a colorkey => promote to alpha
if (!SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
@@ -1721,6 +1719,9 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
}
}
surface_colorspace = SDL_GetSurfaceColorspace(surface);
texture_colorspace = surface_colorspace;
if (surface_colorspace == SDL_COLORSPACE_SRGB_LINEAR ||
SDL_COLORSPACETRANSFER(surface_colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
if (SDL_ISPIXELFORMAT_FLOAT(format)) {
@@ -1962,8 +1963,6 @@ bool SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode)
bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
SDL_Renderer *renderer;
CHECK_TEXTURE_MAGIC(texture, false);
if (scaleMode != SDL_SCALEMODE_NEAREST &&
@@ -1971,12 +1970,10 @@ bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
return SDL_InvalidParamError("scaleMode");
}
renderer = texture->renderer;
texture->scaleMode = scaleMode;
if (texture->native) {
return SDL_SetTextureScaleMode(texture->native, scaleMode);
} else {
renderer->SetTextureScaleMode(renderer, texture, scaleMode);
}
return true;
}
@@ -2576,7 +2573,7 @@ static void UpdateLogicalPresentation(SDL_Renderer *renderer)
const float logical_h = view->logical_h;
int iwidth, iheight;
if (renderer->target) {
if (!is_main_view && renderer->target) {
iwidth = (int)renderer->target->w;
iheight = (int)renderer->target->h;
} else {
@@ -3934,8 +3931,7 @@ bool SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_F
real_srcrect.w = (float)texture->w;
real_srcrect.h = (float)texture->h;
if (srcrect) {
if (!SDL_GetRectIntersectionFloat(srcrect, &real_srcrect, &real_srcrect) ||
real_srcrect.w == 0.0f || real_srcrect.h == 0.0f) {
if (!SDL_GetRectIntersectionFloat(srcrect, &real_srcrect, &real_srcrect)) {
return true;
}
}
@@ -5493,7 +5489,8 @@ bool SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync)
}
#endif
if (!renderer->SetVSync) {
if (!renderer->SetVSync ||
!renderer->SetVSync(renderer, vsync)) {
switch (vsync) {
case 0:
renderer->simulate_vsync = false;
@@ -5504,12 +5501,6 @@ bool SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync)
default:
return SDL_Unsupported();
}
} else if (!renderer->SetVSync(renderer, vsync)) {
if (vsync == 1) {
renderer->simulate_vsync = true;
} else {
return false;
}
}
SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_VSYNC_NUMBER, vsync);
return true;
+2 -1
View File
@@ -34,6 +34,7 @@ extern "C" {
typedef enum SDL_TextureAddressMode
{
SDL_TEXTURE_ADDRESS_INVALID = -1,
SDL_TEXTURE_ADDRESS_AUTO,
SDL_TEXTURE_ADDRESS_CLAMP,
SDL_TEXTURE_ADDRESS_WRAP,
@@ -155,6 +156,7 @@ typedef struct SDL_RenderCommand
SDL_FColor color;
SDL_BlendMode blend;
SDL_Texture *texture;
SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode;
} draw;
struct
@@ -224,7 +226,6 @@ struct SDL_Renderer
bool (*LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, void **pixels, int *pitch);
void (*UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture);
void (*SetTextureScaleMode)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode);
bool (*SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture);
SDL_Surface *(*RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect);
bool (*RenderPresent)(SDL_Renderer *renderer);
+46 -37
View File
@@ -60,7 +60,7 @@ typedef struct
bool updateSize;
bool beginScene;
bool enableSeparateAlphaBlend;
D3DTEXTUREFILTERTYPE scaleMode[3];
SDL_ScaleMode scaleMode[3];
SDL_TextureAddressMode addressMode[3];
IDirect3DSurface9 *defaultRenderTarget;
IDirect3DSurface9 *currentRenderTarget;
@@ -89,7 +89,6 @@ typedef struct
typedef struct
{
D3D_TextureRep texture;
D3DTEXTUREFILTERTYPE scaleMode;
D3D9_Shader shader;
const float *shader_params;
@@ -274,10 +273,14 @@ static void D3D_InitRenderState(D3D_RenderData *data)
IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
// Reset our current scale mode
SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
for (int i = 0; i < SDL_arraysize(data->scaleMode); ++i) {
data->scaleMode[i] = SDL_SCALEMODE_INVALID;
}
// Reset our current address mode
SDL_zeroa(data->addressMode);
for (int i = 0; i < SDL_arraysize(data->addressMode); ++i) {
data->addressMode[i] = SDL_TEXTURE_ADDRESS_INVALID;
}
// Start the render with beginScene
data->beginScene = true;
@@ -533,7 +536,6 @@ static bool D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
if (!texturedata) {
return false;
}
texturedata->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
texture->internal = texturedata;
@@ -736,17 +738,6 @@ static void D3D_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
}
static void D3D_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
if (!texturedata) {
return;
}
texturedata->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
}
static bool D3D_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *texture)
{
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
@@ -926,12 +917,22 @@ static bool BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DW
return true;
}
static void UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
static void UpdateTextureScaleMode(D3D_RenderData *data, SDL_ScaleMode scaleMode, unsigned index)
{
if (texturedata->scaleMode != data->scaleMode[index]) {
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, texturedata->scaleMode);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, texturedata->scaleMode);
data->scaleMode[index] = texturedata->scaleMode;
if (scaleMode != data->scaleMode[index]) {
switch (scaleMode) {
case SDL_SCALEMODE_NEAREST:
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_POINT);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
break;
case SDL_SCALEMODE_LINEAR:
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
break;
default:
break;
}
data->scaleMode[index] = scaleMode;
}
}
@@ -954,7 +955,7 @@ static void UpdateTextureAddressMode(D3D_RenderData *data, SDL_TextureAddressMod
}
}
static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_TextureAddressMode addressMode, D3D9_Shader *shader, const float **shader_params)
static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Shader *shader, const float **shader_params)
{
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
@@ -962,9 +963,6 @@ static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_Te
return SDL_SetError("Texture is not currently available");
}
UpdateTextureScaleMode(data, texturedata, 0);
UpdateTextureAddressMode(data, addressMode, 0);
*shader = texturedata->shader;
*shader_params = texturedata->shader_params;
@@ -973,11 +971,6 @@ static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_Te
}
#ifdef SDL_HAVE_YUV
if (texturedata->yuv) {
UpdateTextureScaleMode(data, texturedata, 1);
UpdateTextureScaleMode(data, texturedata, 2);
UpdateTextureAddressMode(data, addressMode, 1);
UpdateTextureAddressMode(data, addressMode, 2);
if (!BindTextureRep(data->device, &texturedata->utexture, 1)) {
return false;
}
@@ -1012,7 +1005,7 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
}
#endif
if (texture && !SetupTextureState(data, texture, cmd->data.draw.texture_address_mode, &shader, &shader_params)) {
if (texture && !SetupTextureState(data, texture, &shader, &shader_params)) {
return false;
}
@@ -1040,13 +1033,30 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
data->drawstate.texture = texture;
} else if (texture) {
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
UpdateDirtyTexture(data->device, &texturedata->texture);
if (texturedata) {
UpdateDirtyTexture(data->device, &texturedata->texture);
#ifdef SDL_HAVE_YUV
if (texturedata->yuv) {
UpdateDirtyTexture(data->device, &texturedata->utexture);
UpdateDirtyTexture(data->device, &texturedata->vtexture);
if (texturedata->yuv) {
UpdateDirtyTexture(data->device, &texturedata->utexture);
UpdateDirtyTexture(data->device, &texturedata->vtexture);
}
#endif // SDL_HAVE_YUV
}
#endif
}
if (texture) {
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 0);
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 0);
#ifdef SDL_HAVE_YUV
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
if (texturedata && texturedata->yuv) {
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 1);
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 2);
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 1);
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 2);
}
#endif // SDL_HAVE_YUV
}
if (blend != data->drawstate.blend) {
@@ -1653,7 +1663,6 @@ static bool D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
#endif
renderer->LockTexture = D3D_LockTexture;
renderer->UnlockTexture = D3D_UnlockTexture;
renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
renderer->SetRenderTarget = D3D_SetRenderTarget;
renderer->QueueSetViewport = D3D_QueueNoOp;
renderer->QueueSetDrawColor = D3D_QueueNoOp;
+4 -18
View File
@@ -122,7 +122,6 @@ typedef struct
ID3D11Texture2D *stagingTexture;
int lockedTexturePositionX;
int lockedTexturePositionY;
D3D11_FILTER scaleMode;
D3D11_Shader shader;
const float *YCbCr_matrix;
#ifdef SDL_HAVE_YUV
@@ -1172,7 +1171,6 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
if (!textureData) {
return false;
}
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
texture->internal = textureData;
@@ -1796,17 +1794,6 @@ static void D3D11_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
SAFE_RELEASE(textureData->stagingTexture);
}
static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->internal;
if (!textureData) {
return;
}
textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
}
static bool D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
@@ -2318,8 +2305,8 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D11_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (textureData->scaleMode) {
case D3D11_FILTER_MIN_MAG_MIP_POINT:
switch (cmd->data.draw.texture_scale_mode) {
case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_NEAREST_CLAMP];
@@ -2331,7 +2318,7 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
case D3D11_FILTER_MIN_MAG_MIP_LINEAR:
case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_LINEAR_CLAMP];
@@ -2344,7 +2331,7 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
}
break;
default:
return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
}
#ifdef SDL_HAVE_YUV
if (textureData->yuv) {
@@ -2712,7 +2699,6 @@ static bool D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
#endif
renderer->LockTexture = D3D11_LockTexture;
renderer->UnlockTexture = D3D11_UnlockTexture;
renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
renderer->SetRenderTarget = D3D11_SetRenderTarget;
renderer->QueueSetViewport = D3D11_QueueNoOp;
renderer->QueueSetDrawColor = D3D11_QueueNoOp;
+16 -19
View File
@@ -124,7 +124,6 @@ typedef struct
DXGI_FORMAT mainTextureFormat;
ID3D12Resource *stagingBuffer;
D3D12_RESOURCE_STATES stagingResourceState;
D3D12_FILTER scaleMode;
D3D12_Shader shader;
const float *YCbCr_matrix;
#ifdef SDL_HAVE_YUV
@@ -1574,7 +1573,6 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
if (!textureData) {
return false;
}
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR;
texture->internal = textureData;
textureData->mainTextureFormat = textureFormat;
@@ -1992,6 +1990,10 @@ static bool D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
}
}
#endif // SDL_HAVE_YUV
if (textureData->mainTextureResourceView.ptr == rendererData->currentShaderResource.ptr) {
// We'll need to rebind this resource after updating it
rendererData->currentShaderResource.ptr = 0;
}
return true;
}
@@ -2018,6 +2020,10 @@ static bool D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV)) {
return false;
}
if (textureData->mainTextureResourceView.ptr == rendererData->currentShaderResource.ptr) {
// We'll need to rebind this resource after updating it
rendererData->currentShaderResource.ptr = 0;
}
return true;
}
@@ -2036,10 +2042,13 @@ static bool D3D12_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState)) {
return false;
}
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, UVplane, UVpitch, &textureData->mainResourceState)) {
return false;
}
if (textureData->mainTextureResourceView.ptr == rendererData->currentShaderResource.ptr) {
// We'll need to rebind this resource after updating it
rendererData->currentShaderResource.ptr = 0;
}
return true;
}
#endif
@@ -2244,17 +2253,6 @@ static void D3D12_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
D3D_SAFE_RELEASE(textureData->stagingBuffer);
}
static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->internal;
if (!textureData) {
return;
}
textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR;
}
static bool D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->internal;
@@ -2745,8 +2743,8 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D12_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (textureData->scaleMode) {
case D3D12_FILTER_MIN_MAG_MIP_POINT:
switch (cmd->data.draw.texture_scale_mode) {
case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = &rendererData->samplers[D3D12_SAMPLER_NEAREST_CLAMP];
@@ -2758,7 +2756,7 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
case D3D12_FILTER_MIN_MAG_MIP_LINEAR:
case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = &rendererData->samplers[D3D12_SAMPLER_LINEAR_CLAMP];
@@ -2771,7 +2769,7 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
}
break;
default:
return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
}
#ifdef SDL_HAVE_YUV
if (textureData->yuv) {
@@ -3248,7 +3246,6 @@ bool D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Proper
#endif
renderer->LockTexture = D3D12_LockTexture;
renderer->UnlockTexture = D3D12_UnlockTexture;
renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode;
renderer->SetRenderTarget = D3D12_SetRenderTarget;
renderer->QueueSetViewport = D3D12_QueueNoOp;
renderer->QueueSetDrawColor = D3D12_QueueNoOp;
+8 -11
View File
@@ -335,11 +335,6 @@ static void GPU_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GPU_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
}
static void GPU_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scale_mode)
{
// nothing to do in this backend.
}
static bool GPU_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
@@ -450,7 +445,6 @@ static void GPU_InvalidateCachedState(SDL_Renderer *renderer)
{
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
data->state.render_target = NULL;
data->state.scissor_enabled = false;
}
@@ -494,8 +488,7 @@ static void PushUniforms(GPU_RenderData *data, SDL_RenderCommand *cmd)
SDL_PushGPUVertexUniformData(data->state.command_buffer, 0, &uniforms, sizeof(uniforms));
}
static SDL_GPUSampler **SamplerPointer(
GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
static SDL_GPUSampler **SamplerPointer(GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
{
return &data->samplers[scale_mode][address_mode - 1];
}
@@ -575,7 +568,7 @@ static void Draw(
if (tdata) {
SDL_GPUTextureSamplerBinding sampler_bind;
SDL_zero(sampler_bind);
sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture->scaleMode);
sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture_scale_mode);
sampler_bind.texture = tdata->texture;
SDL_BindGPUFragmentSamplers(pass, 0, &sampler_bind, 1);
}
@@ -785,6 +778,8 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
same texture, we can combine them all into a single draw call. */
SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend;
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode;
const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next;
@@ -795,7 +790,10 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; // can't go any further on this draw call, different render command up next.
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
} else if (nextcmd->data.draw.texture != thistexture ||
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
nextcmd->data.draw.texture_address_mode != thisaddressmode ||
nextcmd->data.draw.blend != thisblend) {
// FIXME should we check address mode too?
break; // can't go any further on this draw call, different texture/blendmode copy up next.
} else {
@@ -1176,7 +1174,6 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
renderer->UpdateTexture = GPU_UpdateTexture;
renderer->LockTexture = GPU_LockTexture;
renderer->UnlockTexture = GPU_UnlockTexture;
renderer->SetTextureScaleMode = GPU_SetTextureScaleMode;
renderer->SetRenderTarget = GPU_SetRenderTarget;
renderer->QueueSetViewport = GPU_QueueNoOp;
renderer->QueueSetDrawColor = GPU_QueueNoOp;
+78 -64
View File
@@ -79,15 +79,10 @@ static const size_t CONSTANTS_OFFSET_DECODE_BT2020_LIMITED = ALIGN_CONSTANTS(16,
static const size_t CONSTANTS_OFFSET_DECODE_BT2020_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT2020_LIMITED + sizeof(float) * 4 * 4);
static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT2020_FULL + sizeof(float) * 4 * 4;
// Sampler types
typedef enum
{
SDL_METAL_SAMPLER_NEAREST_CLAMP,
SDL_METAL_SAMPLER_NEAREST_WRAP,
SDL_METAL_SAMPLER_LINEAR_CLAMP,
SDL_METAL_SAMPLER_LINEAR_WRAP,
SDL_NUM_METAL_SAMPLERS
} SDL_METAL_sampler_type;
#define RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v) \
(((scale_mode == SDL_SCALEMODE_NEAREST) << 0) | \
((address_u == SDL_TEXTURE_ADDRESS_WRAP) << 1) | \
((address_v == SDL_TEXTURE_ADDRESS_WRAP) << 2))
typedef enum SDL_MetalVertexFunction
{
@@ -139,7 +134,7 @@ typedef struct METAL_ShaderPipelines
@property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
@property(nonatomic, retain) id<MTLLibrary> mtllibrary;
@property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
@property(nonatomic, retain) NSMutableArray<id<MTLSamplerState>> *mtlsamplers;
@property(nonatomic, retain) NSMutableDictionary<NSNumber *, id<MTLSamplerState>> *mtlsamplers;
@property(nonatomic, retain) id<MTLBuffer> mtlbufconstants;
@property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices;
@property(nonatomic, assign) SDL_MetalView mtlview;
@@ -1070,10 +1065,6 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
}
static void METAL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
}
static bool METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
@autoreleasepool {
@@ -1299,6 +1290,9 @@ typedef struct
__unsafe_unretained id<MTLBuffer> vertex_buffer;
size_t constants_offset;
SDL_Texture *texture;
SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
bool cliprect_dirty;
bool cliprect_enabled;
SDL_Rect cliprect;
@@ -1456,6 +1450,58 @@ static bool SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
return true;
}
static id<MTLSamplerState> GetSampler(SDL3METAL_RenderData *data, SDL_ScaleMode scale_mode, SDL_TextureAddressMode address_u, SDL_TextureAddressMode address_v)
{
NSNumber *key = [NSNumber numberWithInteger:RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v)];
id<MTLSamplerState> mtlsampler = data.mtlsamplers[key];
if (mtlsampler == nil) {
MTLSamplerDescriptor *samplerdesc;
samplerdesc = [[MTLSamplerDescriptor alloc] init];
switch (scale_mode) {
case SDL_SCALEMODE_NEAREST:
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
break;
case SDL_SCALEMODE_LINEAR:
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
break;
default:
SDL_SetError("Unknown scale mode: %d", scale_mode);
return nil;
}
switch (address_u) {
case SDL_TEXTURE_ADDRESS_CLAMP:
samplerdesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerdesc.sAddressMode = MTLSamplerAddressModeRepeat;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_u);
return nil;
}
switch (address_v) {
case SDL_TEXTURE_ADDRESS_CLAMP:
samplerdesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerdesc.tAddressMode = MTLSamplerAddressModeRepeat;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_v);
return nil;
}
mtlsampler = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
if (mtlsampler == nil) {
SDL_SetError("Couldn't create sampler");
return nil;
}
data.mtlsamplers[key] = mtlsampler;
}
return mtlsampler;
}
static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t constants_offset,
id<MTLBuffer> mtlbufvertex, METAL_DrawStateCache *statecache)
{
@@ -1471,33 +1517,6 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
}
if (texture != statecache->texture) {
id<MTLSamplerState> mtlsampler;
if (texture->scaleMode == SDL_SCALEMODE_NEAREST) {
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
} else {
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
}
[data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0];
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0];
#ifdef SDL_HAVE_YUV
if (texturedata.yuv || texturedata.nv12) {
@@ -1507,6 +1526,20 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
#endif
statecache->texture = texture;
}
if (cmd->data.draw.texture_scale_mode != statecache->texture_scale_mode ||
cmd->data.draw.texture_address_mode != statecache->texture_address_mode_u ||
cmd->data.draw.texture_address_mode != statecache->texture_address_mode_v) {
id<MTLSamplerState> mtlsampler = GetSampler(data, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode, cmd->data.draw.texture_address_mode);
if (mtlsampler == nil) {
return false;
}
[data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0];
statecache->texture_scale_mode = cmd->data.draw.texture_scale_mode;
statecache->texture_address_mode_u = cmd->data.draw.texture_address_mode;
statecache->texture_address_mode_v = cmd->data.draw.texture_address_mode;
}
return true;
}
@@ -1527,6 +1560,9 @@ static bool METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
statecache.vertex_buffer = nil;
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
statecache.texture = NULL;
statecache.texture_scale_mode = SDL_SCALEMODE_INVALID;
statecache.texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID;
statecache.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID;
statecache.shader_constants_dirty = true;
statecache.cliprect_dirty = true;
statecache.viewport_dirty = true;
@@ -1887,7 +1923,6 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
int maxtexsize, quadcount = UINT16_MAX / 4;
UInt16 *indexdata;
size_t indicessize = sizeof(UInt16) * quadcount * 6;
MTLSamplerDescriptor *samplerdesc;
id<MTLCommandQueue> mtlcmdqueue;
id<MTLLibrary> mtllibrary;
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
@@ -2047,27 +2082,7 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
data.allpipelines = NULL;
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
static struct
{
MTLSamplerMinMagFilter filter;
MTLSamplerAddressMode address;
} samplerParams[] = {
{ MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeClampToEdge },
{ MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeRepeat },
{ MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeClampToEdge },
{ MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeRepeat },
};
SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_NUM_METAL_SAMPLERS);
data.mtlsamplers = [[NSMutableArray<id<MTLSamplerState>> alloc] init];
samplerdesc = [[MTLSamplerDescriptor alloc] init];
for (int i = 0; i < SDL_arraysize(samplerParams); ++i) {
samplerdesc.minFilter = samplerParams[i].filter;
samplerdesc.magFilter = samplerParams[i].filter;
samplerdesc.sAddressMode = samplerParams[i].address;
samplerdesc.tAddressMode = samplerParams[i].address;
[data.mtlsamplers addObject:[data.mtldevice newSamplerStateWithDescriptor:samplerdesc]];
}
data.mtlsamplers = [[NSMutableDictionary<NSNumber *, id<MTLSamplerState>> alloc] init];
mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
@@ -2129,7 +2144,6 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
#endif
renderer->LockTexture = METAL_LockTexture;
renderer->UnlockTexture = METAL_UnlockTexture;
renderer->SetTextureScaleMode = METAL_SetTextureScaleMode;
renderer->SetRenderTarget = METAL_SetRenderTarget;
renderer->QueueSetViewport = METAL_QueueSetViewport;
renderer->QueueSetDrawColor = METAL_QueueNoOp;
+89 -76
View File
@@ -137,7 +137,6 @@ typedef struct
void *pixels;
int pitch;
SDL_Rect locked_rect;
#ifdef SDL_HAVE_YUV
// YUV texture support
bool yuv;
@@ -147,7 +146,8 @@ typedef struct
GLuint vtexture;
bool vtexture_external;
#endif
SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode;
GL_FBOList *fbo;
} GL_TextureData;
@@ -447,7 +447,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
GLint internalFormat;
GLenum format, type;
int texture_w, texture_h;
GLenum scaleMode;
GL_ActivateRenderer(renderer);
@@ -536,11 +535,10 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
data->format = format;
data->formattype = type;
scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
data->texture_scale_mode = SDL_SCALEMODE_INVALID;
data->texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID;
renderdata->glEnable(textype);
renderdata->glBindTexture(textype, data->texture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode);
#ifdef SDL_PLATFORM_MACOS
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
@@ -596,19 +594,11 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
}
renderdata->glBindTexture(textype, data->utexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
scaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
scaleMode);
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
renderdata->glBindTexture(textype, data->vtexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
scaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
scaleMode);
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
@@ -625,10 +615,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
renderdata->glGenTextures(1, &data->utexture);
}
renderdata->glBindTexture(textype, data->utexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
scaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
scaleMode);
renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture);
@@ -822,38 +808,6 @@ static void GL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
}
static void GL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
const GLenum textype = renderdata->textype;
GL_TextureData *data = (GL_TextureData *)texture->internal;
GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
renderdata->glBindTexture(textype, data->texture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
#ifdef SDL_HAVE_YUV
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
renderdata->glBindTexture(textype, data->utexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
renderdata->glBindTexture(textype, data->vtexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
}
if (texture->format == SDL_PIXELFORMAT_NV12 ||
texture->format == SDL_PIXELFORMAT_NV21) {
renderdata->glBindTexture(textype, data->utexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
}
#endif
}
static bool GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
GL_RenderData *data = (GL_RenderData *)renderer->internal;
@@ -1120,6 +1074,23 @@ static bool SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, cons
return true;
}
static bool SetTextureScaleMode(GL_RenderData *data, GLenum textype, SDL_ScaleMode scaleMode)
{
switch (scaleMode) {
case SDL_SCALEMODE_NEAREST:
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
break;
case SDL_SCALEMODE_LINEAR:
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
break;
default:
return SDL_SetError("Unknown texture scale mode: %d", scaleMode);
}
return true;
}
static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
{
switch (addressMode) {
@@ -1140,41 +1111,23 @@ static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_Textu
static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
{
SDL_Texture *texture = cmd->data.draw.texture;
const GL_TextureData *texturedata = (GL_TextureData *)texture->internal;
GL_TextureData *texturedata = (GL_TextureData *)texture->internal;
const GLenum textype = data->textype;
SetDrawState(data, cmd, texturedata->shader, texturedata->shader_params);
if (texture != data->drawstate.texture) {
const GLenum textype = data->textype;
#ifdef SDL_HAVE_YUV
if (texturedata->yuv) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
}
data->glActiveTextureARB(GL_TEXTURE2_ARB);
data->glBindTexture(textype, texturedata->vtexture);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
return false;
}
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glActiveTextureARB(GL_TEXTURE1_ARB);
data->glBindTexture(textype, texturedata->utexture);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
return false;
}
}
if (texturedata->nv12) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glActiveTextureARB(GL_TEXTURE1_ARB);
data->glBindTexture(textype, texturedata->utexture);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
return false;
}
}
#endif
if (data->GL_ARB_multitexture_supported) {
@@ -1182,11 +1135,67 @@ static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
}
data->glBindTexture(textype, texturedata->texture);
data->drawstate.texture = texture;
}
if (cmd->data.draw.texture_scale_mode != texturedata->texture_scale_mode) {
#ifdef SDL_HAVE_YUV
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2);
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
return false;
}
data->glActiveTextureARB(GL_TEXTURE1);
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
return false;
}
data->glActiveTextureARB(GL_TEXTURE0);
} else if (texturedata->nv12) {
data->glActiveTextureARB(GL_TEXTURE1);
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
return false;
}
data->glActiveTextureARB(GL_TEXTURE0);
}
#endif
if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
return false;
}
texturedata->texture_scale_mode = cmd->data.draw.texture_scale_mode;
}
if (cmd->data.draw.texture_address_mode != texturedata->texture_address_mode) {
#ifdef SDL_HAVE_YUV
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
return false;
}
data->glActiveTextureARB(GL_TEXTURE1);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
return false;
}
data->glActiveTextureARB(GL_TEXTURE0_ARB);
} else if (texturedata->nv12) {
data->glActiveTextureARB(GL_TEXTURE1);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
return false;
}
data->glActiveTextureARB(GL_TEXTURE0);
}
#endif
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
return false;
}
data->drawstate.texture = texture;
texturedata->texture_address_mode = cmd->data.draw.texture_address_mode;
}
return true;
@@ -1372,6 +1381,8 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
same texture, we can combine them all into a single draw call. */
SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend;
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode;
const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next;
@@ -1381,7 +1392,10 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; // can't go any further on this draw call, different render command up next.
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
} else if (nextcmd->data.draw.texture != thistexture ||
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
nextcmd->data.draw.texture_address_mode != thisaddressmode ||
nextcmd->data.draw.blend != thisblend) {
break; // can't go any further on this draw call, different texture/blendmode copy up next.
} else {
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
@@ -1656,7 +1670,6 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
#endif
renderer->LockTexture = GL_LockTexture;
renderer->UnlockTexture = GL_UnlockTexture;
renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
renderer->SetRenderTarget = GL_SetRenderTarget;
renderer->QueueSetViewport = GL_QueueNoOp;
renderer->QueueSetDrawColor = GL_QueueNoOp;
+98 -61
View File
@@ -76,6 +76,8 @@ typedef struct GLES2_TextureData
GLuint texture_u;
GLuint texture_u_external;
#endif
SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode;
GLES2_FBOList *fbo;
} GLES2_TextureData;
@@ -168,6 +170,7 @@ typedef struct GLES2_RenderData
bool debug_enabled;
bool GL_OES_EGL_image_external_supported;
bool GL_EXT_blend_minmax_supported;
#define SDL_PROC(ret, func, params) ret (APIENTRY *func) params;
@@ -987,8 +990,8 @@ static bool SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, c
}
if (texture) {
SDL_Vertex *verts = (SDL_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->tex_coord);
uintptr_t base = (uintptr_t)vertices + cmd->data.draw.first; // address of first vertex, or base offset when using VBOs.
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)(base + offsetof(SDL_Vertex, tex_coord)));
}
if (!GLES2_SelectProgram(data, imgsrc, texture ? texture->colorspace : SDL_COLORSPACE_SRGB)) {
@@ -1021,14 +1024,31 @@ static bool SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, c
// all drawing commands use this
{
SDL_VertexSolid *verts = (SDL_VertexSolid *)(((Uint8 *)vertices) + cmd->data.draw.first);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->position);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_TRUE /* Normalized */, stride, (const GLvoid *)&verts->color);
uintptr_t base = (uintptr_t)vertices + cmd->data.draw.first; // address of first vertex, or base offset when using VBOs.
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)(base + offsetof(SDL_VertexSolid, position)));
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_TRUE /* Normalized */, stride, (const GLvoid *)(base + offsetof(SDL_VertexSolid, color)));
}
return true;
}
static bool SetTextureScaleMode(GLES2_RenderData *data, GLenum textype, SDL_ScaleMode scaleMode)
{
switch (scaleMode) {
case SDL_SCALEMODE_NEAREST:
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
break;
case SDL_SCALEMODE_LINEAR:
data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
break;
default:
return SDL_SetError("Unknown texture scale mode: %d", scaleMode);
}
return true;
}
static bool SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
{
switch (addressMode) {
@@ -1051,6 +1071,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
SDL_Texture *texture = cmd->data.draw.texture;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
int ret;
// Pick an appropriate shader
@@ -1172,19 +1193,66 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
ret = SetDrawState(data, cmd, sourceType, vertices);
if (texture != data->drawstate.texture) {
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
#ifdef SDL_HAVE_YUV
if (tdata->yuv) {
data->glActiveTexture(GL_TEXTURE2);
data->glBindTexture(tdata->texture_type, tdata->texture_v);
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
} else if (tdata->nv12) {
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
}
#endif
data->glBindTexture(tdata->texture_type, tdata->texture);
data->drawstate.texture = texture;
}
if (cmd->data.draw.texture_scale_mode != tdata->texture_scale_mode) {
#ifdef SDL_HAVE_YUV
if (tdata->yuv) {
data->glActiveTexture(GL_TEXTURE2);
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
return false;
}
data->glActiveTexture(GL_TEXTURE1);
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
return false;
}
data->glActiveTexture(GL_TEXTURE0);
} else if (tdata->nv12) {
data->glActiveTexture(GL_TEXTURE1);
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
return false;
}
data->glActiveTexture(GL_TEXTURE0);
}
#endif
if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) {
return false;
}
tdata->texture_scale_mode = cmd->data.draw.texture_scale_mode;
}
if (cmd->data.draw.texture_address_mode != tdata->texture_address_mode) {
#ifdef SDL_HAVE_YUV
if (tdata->yuv) {
data->glActiveTexture(GL_TEXTURE2);
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
return false;
}
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
return false;
}
@@ -1192,8 +1260,6 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
data->glActiveTexture(GL_TEXTURE0);
} else if (tdata->nv12) {
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
return false;
}
@@ -1201,13 +1267,11 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
data->glActiveTexture(GL_TEXTURE0);
}
#endif
data->glBindTexture(tdata->texture_type, tdata->texture);
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
return false;
}
data->drawstate.texture = texture;
tdata->texture_address_mode = cmd->data.draw.texture_address_mode;
}
return ret;
@@ -1269,7 +1333,8 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
data->current_vertex_buffer = 0;
}
vertices = NULL; // attrib pointers will be offsets into the VBO.
// attrib pointers will be offsets into the VBO.
vertices = (void *)(uintptr_t)0; // must be the exact value 0, not NULL (the representation of NULL is not guaranteed to be 0).
#endif
while (cmd) {
@@ -1384,6 +1449,8 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
same texture, we can combine them all into a single draw call. */
SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend;
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode;
const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next;
@@ -1393,7 +1460,10 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; // can't go any further on this draw call, different render command up next.
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
} else if (nextcmd->data.draw.texture != thistexture ||
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
nextcmd->data.draw.texture_address_mode != thisaddressmode ||
nextcmd->data.draw.blend != thisblend) {
break; // can't go any further on this draw call, different texture/blendmode copy up next.
} else {
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
@@ -1486,7 +1556,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
GLES2_TextureData *data;
GLenum format;
GLenum type;
GLenum scaleMode;
GLES2_ActivateRenderer(renderer);
@@ -1512,9 +1581,12 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
#endif
#ifdef GL_TEXTURE_EXTERNAL_OES
case SDL_PIXELFORMAT_EXTERNAL_OES:
format = GL_NONE;
type = GL_NONE;
break;
if (renderdata->GL_OES_EGL_image_external_supported) {
format = GL_NONE;
type = GL_NONE;
break;
}
SDL_FALLTHROUGH;
#endif
default:
return SDL_SetError("Texture format not supported");
@@ -1544,7 +1616,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
data->texture_u = 0;
data->texture_v = 0;
#endif
scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
data->texture_scale_mode = SDL_SCALEMODE_INVALID;
data->texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID;
// Allocate a blob for image renderdata
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
@@ -1583,8 +1656,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
}
renderdata->glActiveTexture(GL_TEXTURE2);
renderdata->glBindTexture(data->texture_type, data->texture_v);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v);
@@ -1599,8 +1670,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
}
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
return false;
@@ -1622,8 +1691,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
}
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
return false;
@@ -1648,8 +1715,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
texture->internal = data;
renderdata->glActiveTexture(GL_TEXTURE0);
renderdata->glBindTexture(data->texture_type, data->texture);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
@@ -1900,37 +1965,6 @@ static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
}
static void GLES2_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->internal;
GLES2_TextureData *data = (GLES2_TextureData *)texture->internal;
GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
#ifdef SDL_HAVE_YUV
if (data->yuv) {
renderdata->glActiveTexture(GL_TEXTURE2);
renderdata->glBindTexture(data->texture_type, data->texture_v);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
} else if (data->nv12) {
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
}
#endif
renderdata->glActiveTexture(GL_TEXTURE0);
renderdata->glBindTexture(data->texture_type, data->texture);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
}
static bool GLES2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
@@ -2151,7 +2185,6 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
#endif
renderer->LockTexture = GLES2_LockTexture;
renderer->UnlockTexture = GLES2_UnlockTexture;
renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode;
renderer->SetRenderTarget = GLES2_SetRenderTarget;
renderer->QueueSetViewport = GLES2_QueueNoOp;
renderer->QueueSetDrawColor = GLES2_QueueNoOp;
@@ -2172,7 +2205,11 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
#endif
#ifdef GL_TEXTURE_EXTERNAL_OES
if (GLES2_CacheShader(data, GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES, GL_FRAGMENT_SHADER)) {
if (SDL_GL_ExtensionSupported("GL_OES_EGL_image_external")) {
data->GL_OES_EGL_image_external_supported = true;
if (!GLES2_CacheShader(data, GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES, GL_FRAGMENT_SHADER)) {
goto error;
}
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_EXTERNAL_OES);
}
#endif
+10 -16
View File
@@ -195,21 +195,6 @@ static bool PS2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
return true;
}
static void PS2_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
GSTEXTURE *ps2_texture = (GSTEXTURE *)texture->internal;
/*
set texture filtering according to scaleMode
supported hint values are nearest (0, default) or linear (1)
gskit scale mode is either GS_FILTER_NEAREST (good for tile-map)
or GS_FILTER_LINEAR (good for scaling)
*/
uint32_t gsKitScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST
? GS_FILTER_NEAREST
: GS_FILTER_LINEAR);
ps2_texture->Filter = gsKitScaleMode;
}
static bool PS2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
return true;
@@ -458,6 +443,16 @@ static bool PS2_RenderGeometry(SDL_Renderer *renderer, void *vertices, SDL_Rende
const GSPRIMUVPOINT *verts = (GSPRIMUVPOINT *) (vertices + cmd->data.draw.first);
GSTEXTURE *ps2_tex = (GSTEXTURE *)cmd->data.draw.texture->internal;
switch (cmd->data.draw.texture_scale_mode) {
case SDL_SCALEMODE_NEAREST:
ps2_tex->Filter = GS_FILTER_NEAREST;
break;
case SDL_SCALEMODE_LINEAR:
ps2_tex->Filter = GS_FILTER_LINEAR;
break;
default:
break;
}
gsKit_TexManager_bind(data->gsGlobal, ps2_tex);
gsKit_prim_list_triangle_goraud_texture_uv_3d(data->gsGlobal, ps2_tex, count, verts);
} else {
@@ -695,7 +690,6 @@ static bool PS2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
renderer->UpdateTexture = PS2_UpdateTexture;
renderer->LockTexture = PS2_LockTexture;
renderer->UnlockTexture = PS2_UnlockTexture;
renderer->SetTextureScaleMode = PS2_SetTextureScaleMode;
renderer->SetRenderTarget = PS2_SetRenderTarget;
renderer->QueueSetViewport = PS2_QueueSetViewport;
renderer->QueueSetDrawColor = PS2_QueueNoOp;
+49 -13
View File
@@ -75,6 +75,8 @@ typedef struct
unsigned int color;
int shadeModel;
SDL_Texture *texture;
SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode;
} PSP_BlendState;
typedef struct
@@ -538,20 +540,44 @@ static bool TextureShouldSwizzle(PSP_TextureData *psp_texture, SDL_Texture *text
return !((texture->access == SDL_TEXTUREACCESS_TARGET) && InVram(psp_texture->data)) && texture->access != SDL_TEXTUREACCESS_STREAMING && (texture->w >= 16 || texture->h >= 16);
}
static void SetTextureAddressMode(SDL_TextureAddressMode addressMode)
{
switch (addressMode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
sceGuTexWrap(GU_CLAMP, GU_CLAMP);
break;
case SDL_TEXTURE_ADDRESS_WRAP:
sceGuTexWrap(GU_REPEAT, GU_REPEAT);
break;
default:
break;
}
}
static void SetTextureScaleMode(SDL_ScaleMode scaleMode)
{
switch (scaleMode) {
case SDL_SCALEMODE_NEAREST:
sceGuTexFilter(GU_NEAREST, GU_NEAREST);
break;
case SDL_SCALEMODE_LINEAR:
sceGuTexFilter(GU_LINEAR, GU_LINEAR);
break;
default:
break;
}
}
static void TextureActivate(SDL_Texture *texture)
{
PSP_TextureData *psp_texture = (PSP_TextureData *)texture->internal;
int scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GU_NEAREST : GU_LINEAR;
// Swizzling is useless with small textures.
if (TextureShouldSwizzle(psp_texture, texture)) {
TextureSwizzle(psp_texture, NULL);
}
sceGuTexWrap(GU_REPEAT, GU_REPEAT);
sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled);
sceGuTexFilter(scaleMode, scaleMode); // GU_NEAREST good for tile-map
// GU_LINEAR good for scaling
sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data);
}
@@ -608,11 +634,6 @@ static void PSP_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch);
}
static void PSP_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
// Nothing to do because TextureActivate takes care of it
}
static bool PSP_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
return true;
@@ -1034,6 +1055,11 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
}
}
if (state->texture) {
SetTextureScaleMode(state->texture_scale_mode);
SetTextureAddressMode(state->texture_address_mode);
}
*current = *state;
}
@@ -1117,6 +1143,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
PSP_BlendState state = {
.color = drawstate.color,
.texture = NULL,
.texture_scale_mode = SDL_SCALEMODE_INVALID,
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID,
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
};
@@ -1132,6 +1160,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
PSP_BlendState state = {
.color = drawstate.color,
.texture = NULL,
.texture_scale_mode = SDL_SCALEMODE_INVALID,
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID,
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
};
@@ -1147,6 +1177,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
PSP_BlendState state = {
.color = drawstate.color,
.texture = NULL,
.texture_scale_mode = SDL_SCALEMODE_INVALID,
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID,
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
};
@@ -1162,6 +1194,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
PSP_BlendState state = {
.color = drawstate.color,
.texture = cmd->data.draw.texture,
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
.texture_address_mode = cmd->data.draw.texture_address_mode,
.mode = cmd->data.draw.blend,
.shadeModel = GU_SMOOTH
};
@@ -1176,6 +1210,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
PSP_BlendState state = {
.color = drawstate.color,
.texture = cmd->data.draw.texture,
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
.texture_address_mode = cmd->data.draw.texture_address_mode,
.mode = cmd->data.draw.blend,
.shadeModel = GU_SMOOTH
};
@@ -1197,11 +1233,12 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
const VertTCV *verts = (VertTCV *)(gpumem + cmd->data.draw.first);
PSP_BlendState state = {
.color = drawstate.color,
.texture = NULL,
.texture = cmd->data.draw.texture,
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
.texture_address_mode = cmd->data.draw.texture_address_mode,
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
.shadeModel = GU_SMOOTH
};
TextureActivate(cmd->data.draw.texture);
PSP_SetBlendState(data, &state);
sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
}
@@ -1310,7 +1347,6 @@ static bool PSP_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
renderer->UpdateTexture = PSP_UpdateTexture;
renderer->LockTexture = PSP_LockTexture;
renderer->UnlockTexture = PSP_UnlockTexture;
renderer->SetTextureScaleMode = PSP_SetTextureScaleMode;
renderer->SetRenderTarget = PSP_SetRenderTarget;
renderer->QueueSetViewport = PSP_QueueNoOp;
renderer->QueueSetDrawColor = PSP_QueueNoOp;
+10 -15
View File
@@ -171,10 +171,6 @@ static void SW_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
}
static void SW_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
}
static bool SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
SW_RenderData *data = (SW_RenderData *)renderer->internal;
@@ -317,7 +313,7 @@ static bool Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *sur
static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture,
const SDL_Rect *srcrect, const SDL_Rect *final_rect,
const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y)
const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y, const SDL_ScaleMode scaleMode)
{
SDL_Surface *src = (SDL_Surface *)texture->internal;
SDL_Rect tmp_rect;
@@ -412,7 +408,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
result = false;
} else {
SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE);
result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode);
result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, scaleMode);
SDL_DestroySurface(src_clone);
src_clone = src_scaled;
src_scaled = NULL;
@@ -429,7 +425,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, center,
&rect_dest, &cangle, &sangle);
src_rotated = SDLgfx_rotateSurface(src_clone, angle,
(texture->scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
(scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
&rect_dest, cangle, sangle, center);
if (!src_rotated) {
result = false;
@@ -460,7 +456,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
}
// Renderer scaling, if needed
result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode);
} else {
/* The NONE blend mode requires three steps to get the pixels onto the destination surface.
* First, the area where the rotated pixels will be blitted to get set to zero.
@@ -470,7 +466,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDL_Rect mask_rect = tmp_rect;
SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE);
// Renderer scaling, if needed
result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode);
if (result) {
/* The next step copies the alpha value. This is done with the BLEND blend mode and
* by modulating the source colors with 0. Since the destination is all zeros, this
@@ -479,7 +475,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
mask_rect = tmp_rect;
// Renderer scaling, if needed
result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode);
if (result) {
/* The last step gets the color values in place. The ADD blend mode simply adds them to
* the destination (where the color values are all zero). However, because the ADD blend
@@ -492,7 +488,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
} else {
SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
// Renderer scaling, if needed
result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode);
SDL_DestroySurface(src_rotated_rgb);
}
}
@@ -858,7 +854,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
SDL_SetSurfaceColorMod(src, 255, 255, 255);
SDL_SetSurfaceAlphaMod(src, 255);
SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode);
SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, cmd->data.draw.texture_scale_mode);
SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod);
SDL_SetSurfaceAlphaMod(tmp, alphaMod);
@@ -869,7 +865,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
// No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy()
}
} else {
SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode);
SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, cmd->data.draw.texture_scale_mode);
}
}
break;
@@ -889,7 +885,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, &copydata->srcrect,
&copydata->dstrect, copydata->angle, &copydata->center, copydata->flip,
copydata->scale_x, copydata->scale_y);
copydata->scale_x, copydata->scale_y, cmd->data.draw.texture_scale_mode);
break;
}
@@ -1135,7 +1131,6 @@ bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, S
renderer->UpdateTexture = SW_UpdateTexture;
renderer->LockTexture = SW_LockTexture;
renderer->UnlockTexture = SW_UnlockTexture;
renderer->SetTextureScaleMode = SW_SetTextureScaleMode;
renderer->SetRenderTarget = SW_SetRenderTarget;
renderer->QueueSetViewport = SW_QueueNoOp;
renderer->QueueSetDrawColor = SW_QueueNoOp;
+36 -25
View File
@@ -70,8 +70,6 @@ static bool VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer,
SDL_Texture *texture);
static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode);
static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer,
SDL_Texture *texture);
@@ -216,7 +214,6 @@ static bool VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window,
#endif
renderer->LockTexture = VITA_GXM_LockTexture;
renderer->UnlockTexture = VITA_GXM_UnlockTexture;
renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode;
renderer->SetRenderTarget = VITA_GXM_SetRenderTarget;
renderer->QueueSetViewport = VITA_GXM_QueueNoOp;
renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor;
@@ -295,9 +292,10 @@ static bool VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
return SDL_OutOfMemory();
}
texture->internal = vita_texture;
vita_texture->scale_mode = SDL_SCALEMODE_INVALID;
vita_texture->address_mode = SDL_TEXTURE_ADDRESS_INVALID;
VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode);
texture->internal = vita_texture;
#ifdef SDL_HAVE_YUV
vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
@@ -582,25 +580,6 @@ static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
// This really improves framerate when using lock/unlock.
}
static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal;
/*
set texture filtering according to scaleMode
supported hint values are nearest (0, default) or linear (1)
vitaScaleMode is either SCE_GXM_TEXTURE_FILTER_POINT (good for tile-map)
or SCE_GXM_TEXTURE_FILTER_LINEAR (good for scaling)
*/
int vitaScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST
? SCE_GXM_TEXTURE_FILTER_POINT
: SCE_GXM_TEXTURE_FILTER_LINEAR);
gxm_texture_set_filters(vita_texture->tex, vitaScaleMode, vitaScaleMode);
return;
}
static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
return true;
@@ -909,9 +888,41 @@ static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd
}
}
if (texture) {
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal;
if (cmd->data.draw.texture_scale_mode != vita_texture->scale_mode) {
switch (cmd->data.draw.texture_scale_mode) {
case SDL_SCALEMODE_NEAREST:
gxm_texture_set_filters(vita_texture->tex, SCE_GXM_TEXTURE_FILTER_POINT, SCE_GXM_TEXTURE_FILTER_POINT);
break;
case SDL_SCALEMODE_LINEAR:
gxm_texture_set_filters(vita_texture->tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR);
break;
default:
break;
}
vita_texture->scale_mode = cmd->data.draw.texture_scale_mode;
}
if (cmd->data.draw.texture_address_mode != vita_texture->address_mode) {
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_CLAMP, SCE_GXM_TEXTURE_ADDR_CLAMP);
break;
case SDL_TEXTURE_ADDRESS_WRAP:
gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_REPEAT, SCE_GXM_TEXTURE_ADDR_REPEAT);
break;
default:
break;
}
vita_texture->address_mode = cmd->data.draw.texture_address_mode;
}
}
if (texture != data->drawstate.texture) {
if (texture) {
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)cmd->data.draw.texture->internal;
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal;
sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex);
}
data->drawstate.texture = texture;
@@ -1122,6 +1122,12 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig
return texture;
}
void gxm_texture_set_address_mode(gxm_texture *texture, SceGxmTextureAddrMode u_mode, SceGxmTextureAddrMode v_mode)
{
sceGxmTextureSetUAddrMode(&texture->gxm_tex, u_mode);
sceGxmTextureSetVAddrMode(&texture->gxm_tex, v_mode);
}
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter)
{
sceGxmTextureSetMinFilter(&texture->gxm_tex, min_filter);
@@ -49,6 +49,7 @@ void gxm_finish(SDL_Renderer *renderer);
gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
void gxm_texture_set_address_mode(gxm_texture *texture, SceGxmTextureAddrMode u_mode, SceGxmTextureAddrMode v_mode);
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
@@ -205,6 +205,8 @@ typedef struct
float wscale;
bool yuv;
bool nv12;
SDL_ScaleMode scale_mode;
SDL_TextureAddressMode address_mode;
} VITA_GXM_TextureData;
#endif // SDL_RENDER_VITA_GXM_TYPES_H
+2 -16
View File
@@ -255,7 +255,6 @@ typedef struct
VkRenderPass mainRenderpasses[VULKAN_RENDERPASS_COUNT];
VkFramebuffer mainFramebuffer;
VULKAN_Buffer stagingBuffer;
VkFilter scaleMode;
SDL_Rect lockedRect;
int width;
int height;
@@ -2600,7 +2599,6 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
} else {
textureData->shader = SHADER_ADVANCED;
}
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
#ifdef SDL_HAVE_YUV
// YUV textures must have even width and height. Also create Ycbcr conversion
@@ -3093,17 +3091,6 @@ static void VULKAN_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
VULKAN_DestroyBuffer(rendererData, &textureData->stagingBuffer);
}
static void VULKAN_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
if (!textureData) {
return;
}
textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
}
static bool VULKAN_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
@@ -3775,7 +3762,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (textureData->scaleMode) {
switch (cmd->data.draw.texture_scale_mode) {
case VK_FILTER_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
@@ -3801,7 +3788,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
}
break;
default:
return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
}
if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
@@ -4290,7 +4277,6 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
#endif
renderer->LockTexture = VULKAN_LockTexture;
renderer->UnlockTexture = VULKAN_UnlockTexture;
renderer->SetTextureScaleMode = VULKAN_SetTextureScaleMode;
renderer->SetRenderTarget = VULKAN_SetRenderTarget;
renderer->QueueSetViewport = VULKAN_QueueNoOp;
renderer->QueueSetDrawColor = VULKAN_QueueNoOp;
+6
View File
@@ -533,6 +533,7 @@ void *SDL_aligned_alloc(size_t alignment, size_t size)
{
size_t padding;
Uint8 *result = NULL;
size_t requested_size = size;
if (alignment < sizeof(void*)) {
alignment = sizeof(void*);
@@ -552,6 +553,11 @@ void *SDL_aligned_alloc(size_t alignment, size_t size)
// Store the original pointer right before the returned value
SDL_memcpy(result - sizeof(original), &original, sizeof(original));
// Initialize the padding to zero
if (padding > 0) {
SDL_memset(result + requested_size, 0, padding);
}
}
}
return result;
+10 -14
View File
@@ -368,14 +368,12 @@ static size_t SDL_ScanUnsignedLongLongInternal(const char *text, int count, int
negative = *text == '-';
++text;
}
if ((radix == 0 || radix == 16) && *text == '0' && text[1] != '\0') {
if ((radix == 0 || radix == 16) && *text == '0' && (text[1] == 'x' || text[1] == 'X')) {
text += 2;
radix = 16;
} else if (radix == 0 && *text == '0' && (text[1] >= '0' && text[1] <= '9')) {
++text;
if (*text == 'x' || *text == 'X') {
radix = 16;
++text;
} else if (radix == 0) {
radix = 8;
}
radix = 8;
} else if (radix == 0) {
radix = 10;
}
@@ -462,14 +460,12 @@ static size_t SDL_ScanUnsignedLongLongInternalW(const wchar_t *text, int count,
negative = *text == '-';
++text;
}
if ((radix == 0 || radix == 16) && *text == '0') {
if ((radix == 0 || radix == 16) && *text == '0' && (text[1] == 'x' || text[1] == 'X')) {
text += 2;
radix = 16;
} else if (radix == 0 && *text == '0' && (text[1] >= '0' && text[1] <= '9')) {
++text;
if (*text == 'x' || *text == 'X') {
radix = 16;
++text;
} else if (radix == 0) {
radix = 8;
}
radix = 8;
} else if (radix == 0) {
radix = 10;
}
-1
View File
@@ -55,7 +55,6 @@ static const char *video_usage[] = {
"[--input-focus]",
"[--keyboard-grab]",
"[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
"[--logical-scale-quality nearest|linear|best]",
"[--logical WxH]",
"[--max-geometry WxH]",
"[--maximize]",
+1
View File
@@ -454,4 +454,5 @@ void SDLTest_LogAllocations(void)
#undef ADD_LINE
SDL_Log("%s", message);
SDL_free_orig(message);
}
+1 -1
View File
@@ -102,7 +102,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem)
void SDL_SignalSemaphore(SDL_Semaphore *sem)
{
if (sem) {
if (!sem) {
return;
}
+17
View File
@@ -27,6 +27,7 @@
#include <langinfo.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#if !defined(HAVE_CLOCK_GETTIME) && defined(SDL_PLATFORM_APPLE)
#include <mach/clock.h>
@@ -186,7 +187,23 @@ bool SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime *dt, bool localTime)
dt->second = tm->tm_sec;
dt->nanosecond = ticks % SDL_NS_PER_SECOND;
dt->day_of_week = tm->tm_wday;
/* tm_gmtoff wasn't formally standardized until POSIX.1-2024, but practically it has been available on desktop
* *nix platforms such as Linux/glibc, FreeBSD, OpenBSD, NetBSD, OSX/macOS, and others since the 1990s.
*
* The notable exception is Solaris, where the timezone offset must still be retrieved in the strictly POSIX.1-2008
* compliant way.
*/
#if (_POSIX_VERSION >= 202405L) || (!defined(sun) && !defined(__sun))
dt->utc_offset = (int)tm->tm_gmtoff;
#else
if (localTime) {
tzset();
dt->utc_offset = (int)timezone;
} else {
dt->utc_offset = 0;
}
#endif
return true;
}
+2 -2
View File
@@ -58,8 +58,8 @@ typedef enum
static gulong (*g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
static void (*g_object_unref)(gpointer object);
static gchar *(*g_mkdtemp)(gchar *template);
gpointer (*g_object_ref_sink)(gpointer object);
gpointer (*g_object_ref)(gpointer object);
static gpointer (*g_object_ref_sink)(gpointer object);
static gpointer (*g_object_ref)(gpointer object);
// glib_typeof requires compiler-specific code and includes that are too complex
// to be worth copy-pasting here
+1 -1
View File
@@ -544,7 +544,7 @@ void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
mii.dwTypeData = label_w;
mii.cch = (UINT) SDL_wcslen(label_w);
if (!SetMenuItemInfoW(entry->parent->hMenu, (UINT) entry->id, TRUE, &mii)) {
if (!SetMenuItemInfoW(entry->parent->hMenu, (UINT) entry->id, FALSE, &mii)) {
SDL_SetError("Couldn't update tray entry label");
}
+47 -5
View File
@@ -22,6 +22,7 @@
#ifdef SDL_HAVE_BLIT_A
#include "SDL_pixels_c.h"
#include "SDL_surface_c.h"
// Functions to perform alpha blended blitting
@@ -968,6 +969,10 @@ static void Blit8888to8888PixelAlphaSwizzle(SDL_BlitInfo *info)
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
bool fill_alpha = !dstfmt->Amask;
Uint32 dstAmask, dstAshift;
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
while (height--) {
int i = 0;
@@ -976,6 +981,9 @@ static void Blit8888to8888PixelAlphaSwizzle(SDL_BlitInfo *info)
Uint32 src32 = *(Uint32 *)src;
Uint32 dst32 = *(Uint32 *)dst;
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
if (fill_alpha) {
dst32 |= dstAmask;
}
*(Uint32 *)dst = dst32;
src += 4;
dst += 4;
@@ -998,6 +1006,10 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
bool fill_alpha = !dstfmt->Amask;
Uint32 dstAmask, dstAshift;
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
// The byte offsets for the start of each pixel
const __m128i mask_offsets = _mm_set_epi8(
@@ -1011,7 +1023,7 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
mask_offsets);
const __m128i alpha_splat_mask = _mm_add_epi8(_mm_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstfmt->Amask);
const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstAmask);
while (height--) {
int i = 0;
@@ -1057,7 +1069,11 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
dst_hi = _mm_mulhi_epu16(dst_hi, _mm_set1_epi16(257));
// Blend the pixels together and save the result
_mm_storeu_si128((__m128i *)dst, _mm_packus_epi16(dst_lo, dst_hi));
dst128 = _mm_packus_epi16(dst_lo, dst_hi);
if (fill_alpha) {
dst128 = _mm_or_si128(dst128, alpha_fill_mask);
}
_mm_storeu_si128((__m128i *)dst, dst128);
src += 16;
dst += 16;
@@ -1067,6 +1083,9 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
Uint32 src32 = *(Uint32 *)src;
Uint32 dst32 = *(Uint32 *)dst;
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
if (fill_alpha) {
dst32 |= dstAmask;
}
*(Uint32 *)dst = dst32;
src += 4;
dst += 4;
@@ -1091,6 +1110,10 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
bool fill_alpha = !dstfmt->Amask;
Uint32 dstAmask, dstAshift;
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
// The byte offsets for the start of each pixel
const __m256i mask_offsets = _mm256_set_epi8(
@@ -1104,7 +1127,7 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
mask_offsets);
const __m256i alpha_splat_mask = _mm256_add_epi8(_mm256_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstfmt->Amask);
const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstAmask);
while (height--) {
int i = 0;
@@ -1150,7 +1173,11 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
dst_hi = _mm256_mulhi_epu16(dst_hi, _mm256_set1_epi16(257));
// Blend the pixels together and save the result
_mm256_storeu_si256((__m256i *)dst, _mm256_packus_epi16(dst_lo, dst_hi));
dst256 = _mm256_packus_epi16(dst_lo, dst_hi);
if (fill_alpha) {
dst256 = _mm256_or_si256(dst256, alpha_fill_mask);
}
_mm256_storeu_si256((__m256i *)dst, dst256);
src += 32;
dst += 32;
@@ -1160,6 +1187,9 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
Uint32 src32 = *(Uint32 *)src;
Uint32 dst32 = *(Uint32 *)dst;
ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
if (fill_alpha) {
dst32 |= dstAmask;
}
*(Uint32 *)dst = dst32;
src += 4;
dst += 4;
@@ -1184,6 +1214,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
bool fill_alpha = !dstfmt->Amask;
Uint32 dstAmask, dstAshift;
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
// The byte offsets for the start of each pixel
const uint8x16_t mask_offsets = vreinterpretq_u8_u64(vcombine_u64(
@@ -1197,7 +1231,7 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
((srcfmt->Bshift >> 3) << dstfmt->Bshift))));
const uint8x16_t alpha_splat_mask = vaddq_u8(vdupq_n_u8(srcfmt->Ashift >> 3), mask_offsets);
const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstfmt->Amask));
const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstAmask));
while (height--) {
int i = 0;
@@ -1242,6 +1276,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
// temp = vraddhn_u16(res_lo, vrshrq_n_u16(res_lo, 8));
// dst128 = vraddhn_high_u16(temp, res_hi, vrshrq_n_u16(res_hi, 8));
if (fill_alpha) {
dst128 = vorrq_u8(dst128, alpha_fill_mask);
}
// Save the result
vst1q_u8(dst, dst128);
@@ -1266,6 +1304,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
dst32 = vaddhn_u16(res, vshrq_n_u16(res, 8));
if (fill_alpha) {
dst32 = vorr_u8(dst32, vget_low_u8(alpha_fill_mask));
}
// Save the result, only low 32-bits
vst1_lane_u32((Uint32*)dst, vreinterpret_u32_u8(dst32), 0);
+267
View File
@@ -22,6 +22,7 @@
#ifdef SDL_HAVE_BLIT_N
#include "SDL_pixels_c.h"
#include "SDL_surface_c.h"
#include "SDL_blit_copy.h"
@@ -2551,6 +2552,255 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info)
}
}
// Convert between two 8888 pixels with differing formats.
#define SWIZZLE_8888_SRC_ALPHA(src, dst, srcfmt, dstfmt) \
do { \
dst = (((src >> srcfmt->Rshift) & 0xFF) << dstfmt->Rshift) | \
(((src >> srcfmt->Gshift) & 0xFF) << dstfmt->Gshift) | \
(((src >> srcfmt->Bshift) & 0xFF) << dstfmt->Bshift) | \
(((src >> srcfmt->Ashift) & 0xFF) << dstfmt->Ashift); \
} while (0)
#define SWIZZLE_8888_DST_ALPHA(src, dst, srcfmt, dstfmt, dstAmask) \
do { \
dst = (((src >> srcfmt->Rshift) & 0xFF) << dstfmt->Rshift) | \
(((src >> srcfmt->Gshift) & 0xFF) << dstfmt->Gshift) | \
(((src >> srcfmt->Bshift) & 0xFF) << dstfmt->Bshift) | \
dstAmask; \
} while (0)
#ifdef SDL_SSE4_1_INTRINSICS
static void SDL_TARGETING("sse4.1") Blit8888to8888PixelSwizzleSSE41(SDL_BlitInfo *info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint8 *src = info->src;
int srcskip = info->src_skip;
Uint8 *dst = info->dst;
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
bool fill_alpha = (!srcfmt->Amask || !dstfmt->Amask);
Uint32 srcAmask, srcAshift;
Uint32 dstAmask, dstAshift;
SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
// The byte offsets for the start of each pixel
const __m128i mask_offsets = _mm_set_epi8(
12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0);
const __m128i convert_mask = _mm_add_epi32(
_mm_set1_epi32(
((srcfmt->Rshift >> 3) << dstfmt->Rshift) |
((srcfmt->Gshift >> 3) << dstfmt->Gshift) |
((srcfmt->Bshift >> 3) << dstfmt->Bshift) |
((srcAshift >> 3) << dstAshift)),
mask_offsets);
const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstAmask);
while (height--) {
int i = 0;
for (; i + 4 <= width; i += 4) {
// Load 4 src pixels
__m128i src128 = _mm_loadu_si128((__m128i *)src);
// Convert to dst format
src128 = _mm_shuffle_epi8(src128, convert_mask);
if (fill_alpha) {
// Set the alpha channels of src to 255
src128 = _mm_or_si128(src128, alpha_fill_mask);
}
// Save the result
_mm_storeu_si128((__m128i *)dst, src128);
src += 16;
dst += 16;
}
for (; i < width; ++i) {
Uint32 src32 = *(Uint32 *)src;
Uint32 dst32;
if (fill_alpha) {
SWIZZLE_8888_DST_ALPHA(src32, dst32, srcfmt, dstfmt, dstAmask);
} else {
SWIZZLE_8888_SRC_ALPHA(src32, dst32, srcfmt, dstfmt);
}
*(Uint32 *)dst = dst32;
src += 4;
dst += 4;
}
src += srcskip;
dst += dstskip;
}
}
#endif
#ifdef SDL_AVX2_INTRINSICS
static void SDL_TARGETING("avx2") Blit8888to8888PixelSwizzleAVX2(SDL_BlitInfo *info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint8 *src = info->src;
int srcskip = info->src_skip;
Uint8 *dst = info->dst;
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
bool fill_alpha = (!srcfmt->Amask || !dstfmt->Amask);
Uint32 srcAmask, srcAshift;
Uint32 dstAmask, dstAshift;
SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
// The byte offsets for the start of each pixel
const __m256i mask_offsets = _mm256_set_epi8(
28, 28, 28, 28, 24, 24, 24, 24, 20, 20, 20, 20, 16, 16, 16, 16, 12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0);
const __m256i convert_mask = _mm256_add_epi32(
_mm256_set1_epi32(
((srcfmt->Rshift >> 3) << dstfmt->Rshift) |
((srcfmt->Gshift >> 3) << dstfmt->Gshift) |
((srcfmt->Bshift >> 3) << dstfmt->Bshift) |
((srcAshift >> 3) << dstAshift)),
mask_offsets);
const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstAmask);
while (height--) {
int i = 0;
for (; i + 8 <= width; i += 8) {
// Load 8 src pixels
__m256i src256 = _mm256_loadu_si256((__m256i *)src);
// Convert to dst format
src256 = _mm256_shuffle_epi8(src256, convert_mask);
if (fill_alpha) {
// Set the alpha channels of src to 255
src256 = _mm256_or_si256(src256, alpha_fill_mask);
}
// Save the result
_mm256_storeu_si256((__m256i *)dst, src256);
src += 32;
dst += 32;
}
for (; i < width; ++i) {
Uint32 src32 = *(Uint32 *)src;
Uint32 dst32;
if (fill_alpha) {
SWIZZLE_8888_DST_ALPHA(src32, dst32, srcfmt, dstfmt, dstAmask);
} else {
SWIZZLE_8888_SRC_ALPHA(src32, dst32, srcfmt, dstfmt);
}
*(Uint32 *)dst = dst32;
src += 4;
dst += 4;
}
src += srcskip;
dst += dstskip;
}
}
#endif
#if defined(SDL_NEON_INTRINSICS) && (__ARM_ARCH >= 8)
static void Blit8888to8888PixelSwizzleNEON(SDL_BlitInfo *info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint8 *src = info->src;
int srcskip = info->src_skip;
Uint8 *dst = info->dst;
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
bool fill_alpha = (!srcfmt->Amask || !dstfmt->Amask);
Uint32 srcAmask, srcAshift;
Uint32 dstAmask, dstAshift;
SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
// The byte offsets for the start of each pixel
const uint8x16_t mask_offsets = vreinterpretq_u8_u64(vcombine_u64(
vcreate_u64(0x0404040400000000), vcreate_u64(0x0c0c0c0c08080808)));
const uint8x16_t convert_mask = vreinterpretq_u8_u32(vaddq_u32(
vreinterpretq_u32_u8(mask_offsets),
vdupq_n_u32(
((srcfmt->Rshift >> 3) << dstfmt->Rshift) |
((srcfmt->Gshift >> 3) << dstfmt->Gshift) |
((srcfmt->Bshift >> 3) << dstfmt->Bshift) |
((srcAshift >> 3) << dstAshift))));
const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstAmask));
while (height--) {
int i = 0;
for (; i + 4 <= width; i += 4) {
// Load 4 src pixels
uint8x16_t src128 = vld1q_u8(src);
// Convert to dst format
src128 = vqtbl1q_u8(src128, convert_mask);
if (fill_alpha) {
// Set the alpha channels of src to 255
src128 = vorrq_u8(src128, alpha_fill_mask);
}
// Save the result
vst1q_u8(dst, src128);
src += 16;
dst += 16;
}
// Process 1 pixel per iteration, max 3 iterations, same calculations as above
for (; i < width; ++i) {
// Top 32-bits will be not used in src32
uint8x8_t src32 = vreinterpret_u8_u32(vld1_dup_u32((Uint32*)src));
// Convert to dst format
src32 = vtbl1_u8(src32, vget_low_u8(convert_mask));
if (fill_alpha) {
// Set the alpha channels of src to 255
src32 = vorr_u8(src32, vget_low_u8(alpha_fill_mask));
}
// Save the result, only low 32-bits
vst1_lane_u32((Uint32*)dst, vreinterpret_u32_u8(src32), 0);
src += 4;
dst += 4;
}
src += srcskip;
dst += dstskip;
}
}
#endif
// Blit_3or4_to_3or4__same_rgb: 3 or 4 bpp, same RGB triplet
static void Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo *info)
{
@@ -2873,6 +3123,23 @@ SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface *surface)
switch (surface->map.info.flags & ~SDL_COPY_RLE_MASK) {
case 0:
if (SDL_PIXELLAYOUT(srcfmt->format) == SDL_PACKEDLAYOUT_8888 &&
SDL_PIXELLAYOUT(dstfmt->format) == SDL_PACKEDLAYOUT_8888) {
#ifdef SDL_AVX2_INTRINSICS
if (SDL_HasAVX2()) {
return Blit8888to8888PixelSwizzleAVX2;
}
#endif
#ifdef SDL_SSE4_1_INTRINSICS
if (SDL_HasSSE41()) {
return Blit8888to8888PixelSwizzleSSE41;
}
#endif
#if defined(SDL_NEON_INTRINSICS) && (__ARM_ARCH >= 8)
return Blit8888to8888PixelSwizzleNEON;
#endif
}
blitfun = NULL;
if (dstfmt->bits_per_pixel > 8) {
Uint32 a_need = NO_ALPHA;
+2 -1
View File
@@ -20,12 +20,13 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_blit.h"
#ifdef SDL_HAVE_BLIT_AUTO
/* *INDENT-OFF* */ // clang-format off
#include "SDL_blit.h"
extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
/* *INDENT-ON* */ // clang-format on
Loaded 100 of 135 files, more files were not shown because too many files have changed in this diff. Show more