update SDL3 to 3.2.10.

This commit is contained in:
Sasha Szpakowski
2025-03-31 20:17:10 -03:00
parent 7b852a67c4
commit 375c6f88cd
104 changed files with 2120 additions and 833 deletions
+15 -1
View File
@@ -356,7 +356,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
if (!SDL_VideoInit(NULL)) {
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
SDL_PushError();
SDL_QuitSubSystem(SDL_INIT_EVENTS);
SDL_PopError();
goto quit_and_error;
}
} else {
@@ -381,7 +383,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
if (!SDL_InitAudio(NULL)) {
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
SDL_PushError();
SDL_QuitSubSystem(SDL_INIT_EVENTS);
SDL_PopError();
goto quit_and_error;
}
} else {
@@ -406,7 +410,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
if (!SDL_InitJoysticks()) {
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
SDL_PushError();
SDL_QuitSubSystem(SDL_INIT_EVENTS);
SDL_PopError();
goto quit_and_error;
}
} else {
@@ -430,7 +436,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
if (!SDL_InitGamepads()) {
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
SDL_PushError();
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
SDL_PopError();
goto quit_and_error;
}
} else {
@@ -493,7 +501,9 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA);
if (!SDL_CameraInit(NULL)) {
SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA);
SDL_PushError();
SDL_QuitSubSystem(SDL_INIT_EVENTS);
SDL_PopError();
goto quit_and_error;
}
} else {
@@ -511,7 +521,11 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
return SDL_ClearError();
quit_and_error:
SDL_QuitSubSystem(flags_initialized);
{
SDL_PushError();
SDL_QuitSubSystem(flags_initialized);
SDL_PopError();
}
return false;
}
+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;
+12
View File
@@ -46,4 +46,16 @@ typedef struct SDL_error
// Defined in SDL_thread.c
extern SDL_error *SDL_GetErrBuf(bool create);
// Macros to save and restore error values
#define SDL_PushError() \
char *saved_error = SDL_strdup(SDL_GetError())
#define SDL_PopError() \
do { \
if (saved_error) { \
SDL_SetError("%s", saved_error); \
SDL_free(saved_error); \
} \
} while (0)
#endif // SDL_error_c_h_
+2 -2
View File
@@ -1256,11 +1256,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;
+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
+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;
+5 -1
View File
@@ -1187,7 +1187,11 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%i", device->sample_frames, device->spec.freq);
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_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);
@@ -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) {
@@ -58,7 +58,9 @@ static bool pipewire_initialized = false;
// Pipewire entry points
static const char *(*PIPEWIRE_pw_get_library_version)(void);
#if PW_CHECK_VERSION(0, 3, 75)
static bool (*PIPEWIRE_pw_check_library_version)(int major, int minor, int micro);
#endif
static void (*PIPEWIRE_pw_init)(int *, char ***);
static void (*PIPEWIRE_pw_deinit)(void);
static struct pw_main_loop *(*PIPEWIRE_pw_main_loop_new)(const struct spa_dict *loop);
@@ -151,7 +153,9 @@ static void unload_pipewire_library(void)
static bool load_pipewire_syms(void)
{
SDL_PIPEWIRE_SYM(pw_get_library_version);
#if PW_CHECK_VERSION(0, 3, 75)
SDL_PIPEWIRE_SYM(pw_check_library_version);
#endif
SDL_PIPEWIRE_SYM(pw_init);
SDL_PIPEWIRE_SYM(pw_deinit);
SDL_PIPEWIRE_SYM(pw_main_loop_new);
@@ -1024,7 +1028,11 @@ static bool hotplug_loop_init(void)
spa_list_init(&hotplug.global_list);
#if PW_CHECK_VERSION(0, 3, 75)
hotplug.have_1_0_5 = PIPEWIRE_pw_check_library_version(1,0,5);
#else
hotplug.have_1_0_5 = false;
#endif
hotplug.loop = PIPEWIRE_pw_thread_loop_new("SDLPwCameraPlug", NULL);
if (!hotplug.loop) {
+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,6,0
PRODUCTVERSION 3,2,6,0
FILEVERSION 3,2,10,0
PRODUCTVERSION 3,2,10,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "3, 2, 6, 0\0"
VALUE "FileVersion", "3, 2, 10, 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, 6, 0\0"
VALUE "ProductVersion", "3, 2, 10, 0\0"
END
END
BLOCK "VarFileInfo"
+18 -1
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
@@ -642,6 +644,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 +1167,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
+6 -4
View File
@@ -110,7 +110,7 @@ typedef struct
} SDL_DisabledEventBlock;
static SDL_DisabledEventBlock *SDL_disabled_events[256];
static Uint32 SDL_userevents = SDL_EVENT_USER;
static SDL_AtomicInt SDL_userevents;
typedef struct SDL_TemporaryMemory
{
@@ -1893,9 +1893,11 @@ Uint32 SDL_RegisterEvents(int numevents)
{
Uint32 event_base = 0;
if ((numevents > 0) && (SDL_userevents + numevents <= SDL_EVENT_LAST)) {
event_base = SDL_userevents;
SDL_userevents += numevents;
if (numevents > 0) {
int value = SDL_AddAtomicInt(&SDL_userevents, numevents);
if (value >= 0 && value <= (SDL_EVENT_LAST - SDL_EVENT_USER)) {
event_base = (Uint32)(SDL_EVENT_USER + value);
}
}
return event_base;
}
+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;
}
+33
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;
@@ -998,6 +1022,12 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI
SDL_SetMouseFocus(window);
}
// Accumulate fractional wheel motion if integer mode is enabled
if (mouse->integer_mode_flags & 2) {
mouse->integer_mode_residual_scroll_x = SDL_modff(mouse->integer_mode_residual_scroll_x + x, &x);
mouse->integer_mode_residual_scroll_y = SDL_modff(mouse->integer_mode_residual_scroll_y + y, &y);
}
if (x == 0.0f && y == 0.0f) {
return;
}
@@ -1108,6 +1138,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,13 @@ 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;
float integer_mode_residual_scroll_x;
float integer_mode_residual_scroll_y;
// Data common to all mice
SDL_Window *focus;
float x;
+5 -2
View File
@@ -2646,8 +2646,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(
+1 -1
View File
@@ -854,7 +854,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!");
+26 -11
View File
@@ -1135,6 +1135,7 @@ struct VulkanRenderer
VulkanMemoryAllocator *memoryAllocator;
VkPhysicalDeviceMemoryProperties memoryProperties;
bool checkEmptyAllocations;
WindowData **claimedWindows;
Uint32 claimedWindowCount;
@@ -1203,6 +1204,7 @@ struct VulkanRenderer
SDL_Mutex *submitLock;
SDL_Mutex *acquireCommandBufferLock;
SDL_Mutex *acquireUniformBufferLock;
SDL_Mutex *renderPassFetchLock;
SDL_Mutex *framebufferFetchLock;
SDL_Mutex *windowLock;
@@ -1577,6 +1579,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);
@@ -4634,7 +4640,11 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainCreateInfo.queueFamilyIndexCount = 0;
swapchainCreateInfo.pQueueFamilyIndices = NULL;
#ifdef SDL_PLATFORM_ANDROID
swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
#else
swapchainCreateInfo.preTransform = swapchainSupportDetails.capabilities.currentTransform;
#endif
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapchainCreateInfo.presentMode = SDLToVK_PresentMode[windowData->presentMode];
swapchainCreateInfo.clipped = VK_TRUE;
@@ -4780,7 +4790,7 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
}
renderer->vkCreateSemaphore(
vulkanResult = renderer->vkCreateSemaphore(
renderer->logicalDevice,
&semaphoreCreateInfo,
NULL,
@@ -4934,6 +4944,7 @@ 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->windowLock);
@@ -7081,12 +7092,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;
}
@@ -7098,6 +7112,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
depthStencilTargetInfo);
if (renderPassHandle == VK_NULL_HANDLE) {
SDL_UnlockMutex(renderer->renderPassFetchLock);
return VK_NULL_HANDLE;
}
@@ -7113,6 +7128,8 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
(const void *)allocedKey,
(const void *)renderPassWrapper, true);
SDL_UnlockMutex(renderer->renderPassFetchLock);
return renderPassHandle;
}
@@ -7181,9 +7198,8 @@ static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
(const void *)&key,
(const void **)&vulkanFramebuffer);
SDL_UnlockMutex(renderer->framebufferFetchLock);
if (findResult) {
SDL_UnlockMutex(renderer->framebufferFetchLock);
return vulkanFramebuffer;
}
@@ -7251,19 +7267,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;
}
@@ -10429,7 +10444,6 @@ static bool VULKAN_Submit(
VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT];
Uint32 swapchainImageIndex;
VulkanTextureSubresource *swapchainTextureSubresource;
Uint8 commandBufferCleaned = 0;
VulkanMemorySubAllocator *allocator;
bool presenting = false;
@@ -10545,12 +10559,10 @@ static bool VULKAN_Submit(
renderer,
renderer->submittedCommandBuffers[i],
false);
commandBufferCleaned = 1;
}
}
if (commandBufferCleaned) {
if (renderer->checkEmptyAllocations) {
SDL_LockMutex(renderer->allocatorLock);
for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
@@ -10566,6 +10578,8 @@ static bool VULKAN_Submit(
}
}
renderer->checkEmptyAllocations = false;
SDL_UnlockMutex(renderer->allocatorLock);
}
@@ -11657,6 +11671,7 @@ 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->windowLock = SDL_CreateMutex();
@@ -11718,7 +11733,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 timing
VULKAN_INTERNAL_RenderPassHashFunction,
VULKAN_INTERNAL_RenderPassHashKeyMatch,
VULKAN_INTERNAL_RenderPassHashDestroy,
+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);
+11 -9
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));
+6
View File
@@ -641,6 +641,12 @@ static const char *s_GamepadMappings[] = {
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"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,",
+57
View File
@@ -427,6 +427,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 +1050,27 @@ static void CleanupSensorFusion(SDL_Joystick *joystick)
}
}
static bool ShouldSwapFaceButtons(const SDL_SteamVirtualGamepadInfo *info)
{
// When "Use Nintendo Button Layout" is enabled under Steam (the default)
// it will send button 0 for the A (east) button and button 1 for the
// B (south) button. This is done so that games that interpret the
// buttons as Xbox input will get button 0 for "A" as they expect.
//
// However, SDL reports positional buttons, so we need to swap
// the buttons so they show up in the correct position. This provides
// consistent behavior regardless of whether we're running under Steam,
// under the default settings.
if (info &&
(info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR)) {
return true;
}
return false;
}
/*
* Open a joystick for use - the index passed as an argument refers to
* the N'th joystick on the system. This index is the value which will
@@ -1094,6 +1122,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
joystick->attached = true;
joystick->led_expiration = SDL_GetTicks();
joystick->battery_percent = -1;
joystick->is_virtual = (driver == &SDL_VIRTUAL_JoystickDriver);
if (!driver->Open(joystick, device_index)) {
SDL_SetObjectValid(joystick, SDL_OBJECT_TYPE_JOYSTICK, false);
@@ -1148,6 +1177,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id);
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 +1255,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 +1275,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 +1295,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 +1315,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 +1335,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 +1355,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);
@@ -2305,6 +2341,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 +2408,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;
}
}
+2
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;
@@ -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;
@@ -1135,12 +1133,13 @@ check_removed:
goto check_removed;
} else {
HIDAPI_DelDevice(device);
device = NULL;
// Update the device list again in case this device comes back
SDL_HIDAPI_change_count = 0;
}
}
if (device->broken && device->parent) {
if (device && device->broken && device->parent) {
HIDAPI_DelDevice(device->parent);
// We deleted a different device here, restart the loop
@@ -160,6 +160,8 @@ struct joystick_hwdata
WindowsGamingInputGamepadState *wgi_slot;
#endif
bool triggers_rumbling;
SDL_RAWINPUT_Device *device;
};
typedef struct joystick_hwdata RAWINPUT_DeviceContext;
@@ -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,11 +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
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
HRESULT hr;
gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
gamepad_state->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
if (!rumbled && ctx->wgi_correlated) {
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);
if (SUCCEEDED(hr)) {
rumbled = true;
@@ -1513,6 +1518,7 @@ static bool RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_
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");
+88 -97
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;
}
@@ -462,8 +460,8 @@ static void UpdatePixelClipRect(SDL_Renderer *renderer, SDL_RenderViewState *vie
{
const float scale_x = view->current_scale.x;
const float scale_y = view->current_scale.y;
view->pixel_clip_rect.x = (int)SDL_floorf((view->clip_rect.x * scale_x) + view->logical_offset.x);
view->pixel_clip_rect.y = (int)SDL_floorf((view->clip_rect.y * scale_y) + view->logical_offset.y);
view->pixel_clip_rect.x = (int)SDL_floorf(view->clip_rect.x * scale_x);
view->pixel_clip_rect.y = (int)SDL_floorf(view->clip_rect.y * scale_y);
view->pixel_clip_rect.w = (int)SDL_ceilf(view->clip_rect.w * scale_x);
view->pixel_clip_rect.h = (int)SDL_ceilf(view->clip_rect.h * scale_y);
}
@@ -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,
@@ -1962,8 +1962,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 +1969,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;
}
@@ -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;
@@ -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;
@@ -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 -10
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;
@@ -494,8 +489,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 +569,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 +779,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 +791,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 +1175,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;
@@ -1070,10 +1070,6 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
}
static void METAL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
}
static bool METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
@autoreleasepool {
@@ -1473,7 +1469,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
if (texture != statecache->texture) {
id<MTLSamplerState> mtlsampler;
if (texture->scaleMode == SDL_SCALEMODE_NEAREST) {
if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_NEAREST) {
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP];
@@ -2129,7 +2125,6 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
#endif
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;
@@ -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;
@@ -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
@@ -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;
}
+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;
+28
View File
@@ -692,6 +692,34 @@ void SDL_QuitPixelFormatDetails(void)
}
}
void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift)
{
if (fmt->Amask) {
*mask = fmt->Amask;
*shift = fmt->Ashift;
} else {
*mask = ~(fmt->Rmask | fmt->Gmask | fmt->Bmask);
switch (*mask) {
case 0x000000FF:
*shift = 0;
break;
case 0x0000FF00:
*shift = 8;
break;
case 0x00FF0000:
*shift = 16;
break;
case 0xFF000000:
*shift = 24;
break;
default:
// Should never happen
*shift = 0;
break;
}
}
}
SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format)
{
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
+1 -1
View File
@@ -29,7 +29,7 @@
// Pixel format functions
extern bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, size_t *size, size_t *pitch, bool minimalPitch);
extern void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift);
extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat pixel_format);
extern void SDL_QuitPixelFormatDetails(void);
+28 -2
View File
@@ -104,6 +104,11 @@ bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, siz
}
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
if (format == SDL_PIXELFORMAT_MJPG) {
// We don't know in advance what it will be, we'll figure it out later.
return true;
}
if (!SDL_CalculateYUVSize(format, width, height, &sz, &p)) {
// Overflow...
return false;
@@ -199,6 +204,11 @@ SDL_Surface *SDL_CreateSurface(int width, int height, SDL_PixelFormat format)
return NULL;
}
if (format == SDL_PIXELFORMAT_UNKNOWN) {
SDL_InvalidParamError("format");
return NULL;
}
if (!SDL_CalculateSurfaceSize(format, width, height, &size, &pitch, false /* not minimal pitch */)) {
// Overflow...
return NULL;
@@ -214,7 +224,7 @@ SDL_Surface *SDL_CreateSurface(int width, int height, SDL_PixelFormat format)
return NULL;
}
if (surface->w && surface->h) {
if (surface->w && surface->h && format != SDL_PIXELFORMAT_MJPG) {
surface->flags &= ~SDL_SURFACE_PREALLOCATED;
surface->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), size);
if (!surface->pixels) {
@@ -245,6 +255,11 @@ SDL_Surface *SDL_CreateSurfaceFrom(int width, int height, SDL_PixelFormat format
return NULL;
}
if (format == SDL_PIXELFORMAT_UNKNOWN) {
SDL_InvalidParamError("format");
return NULL;
}
if (pitch == 0 && !pixels) {
// The application will fill these in later with valid values
} else {
@@ -1917,7 +1932,18 @@ SDL_Surface *SDL_ConvertSurfaceAndColorspace(SDL_Surface *surface, SDL_PixelForm
SDL_SetSurfaceColorspace(convert, colorspace);
if (SDL_ISPIXELFORMAT_FOURCC(format) || SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
if (!SDL_ConvertPixelsAndColorspace(surface->w, surface->h, surface->format, src_colorspace, src_properties, surface->pixels, surface->pitch, convert->format, colorspace, props, convert->pixels, convert->pitch)) {
if (surface->format == SDL_PIXELFORMAT_MJPG && format == SDL_PIXELFORMAT_MJPG) {
// Just do a straight pixel copy of the JPEG image
size_t size = (size_t)surface->pitch;
convert->pixels = SDL_malloc(size);
if (!convert->pixels) {
goto error;
}
convert->flags &= ~SDL_SURFACE_PREALLOCATED;
convert->pitch = surface->pitch;
SDL_memcpy(convert->pixels, surface->pixels, size);
} else if (!SDL_ConvertPixelsAndColorspace(surface->w, surface->h, surface->format, src_colorspace, src_properties, surface->pixels, surface->pitch, convert->format, colorspace, props, convert->pixels, convert->pitch)) {
goto error;
}
+1
View File
@@ -83,6 +83,7 @@ struct SDL_Surface
// Surface functions
extern bool SDL_SurfaceValid(SDL_Surface *surface);
extern void SDL_UpdateSurfaceLockFlag(SDL_Surface *surface);
extern bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, size_t *size, size_t *pitch, bool minimalPitch);
extern float SDL_GetDefaultSDRWhitePoint(SDL_Colorspace colorspace);
extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace colorspace);
extern float SDL_GetDefaultHDRHeadroom(SDL_Colorspace colorspace);
+2
View File
@@ -163,6 +163,8 @@ struct SDL_VideoDisplay
float content_scale;
SDL_HDROutputProperties HDR;
// This is true if we are fullscreen or fullscreen is pending
bool fullscreen_active;
SDL_Window *fullscreen_window;
SDL_VideoDevice *device;
+24 -2
View File
@@ -1435,6 +1435,11 @@ void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode
{
SDL_DisplayMode last_mode;
if (display->fullscreen_active) {
// This is a temporary mode change, don't save the desktop mode
return;
}
SDL_copyp(&last_mode, &display->desktop_mode);
if (display->desktop_mode.internal) {
@@ -1944,6 +1949,8 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
SDL_MinimizeWindow(display->fullscreen_window);
}
display->fullscreen_active = window->fullscreen_exclusive;
if (!SDL_SetDisplayModeForDisplay(display, mode)) {
goto error;
}
@@ -1961,6 +1968,7 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0);
}
} else if (ret == SDL_FULLSCREEN_FAILED) {
display->fullscreen_active = false;
goto error;
}
}
@@ -1976,18 +1984,24 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
* This is also unnecessary on Cocoa, Wayland, Win32, and X11 (will send SDL_EVENT_WINDOW_RESIZED).
*/
if (!SDL_SendsFullscreenDimensions(_this)) {
SDL_Rect displayRect;
if (mode) {
mode_w = mode->w;
mode_h = mode->h;
SDL_GetDisplayBounds(mode->displayID, &displayRect);
} else {
mode_w = display->desktop_mode.w;
mode_h = display->desktop_mode.h;
SDL_GetDisplayBounds(display->id, &displayRect);
}
if (window->w != mode_w || window->h != mode_h) {
resized = true;
}
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, displayRect.x, displayRect.y);
if (resized) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, mode_w, mode_h);
} else {
@@ -2005,6 +2019,8 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
// Restore the desktop mode
if (display) {
display->fullscreen_active = false;
SDL_SetDisplayModeForDisplay(display, NULL);
}
if (commit) {
@@ -2034,6 +2050,7 @@ bool SDL_UpdateFullscreenMode(SDL_Window *window, SDL_FullscreenOp fullscreen, b
}
if (!SDL_SendsFullscreenDimensions(_this)) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, window->windowed.x, window->windowed.y);
if (resized) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->windowed.w, window->windowed.h);
} else {
@@ -2907,11 +2924,12 @@ bool SDL_GetWindowPosition(SDL_Window *window, int *x, int *y)
}
}
} else {
const bool use_pending = (window->flags & SDL_WINDOW_HIDDEN) && window->last_position_pending;
if (x) {
*x = window->x;
*x = use_pending ? window->pending.x : window->x;
}
if (y) {
*y = window->y;
*y = use_pending ? window->pending.y : window->y;
}
}
return true;
@@ -5387,6 +5405,10 @@ bool SDL_GetTextInputMultiline(SDL_PropertiesID props)
static bool AutoShowingScreenKeyboard(void)
{
const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD);
if (!hint) {
// Steam will eventually have smarts about whether a keyboard is active, so always request the on-screen keyboard on Steam Deck
hint = SDL_GetHint("SteamDeck");
}
if (((!hint || SDL_strcasecmp(hint, "auto") == 0) && !SDL_HasKeyboard()) ||
SDL_GetStringBoolean(hint, false)) {
return true;
+31 -13
View File
@@ -1628,26 +1628,44 @@ static bool SDL_ConvertPixels_SwapNV_std(int width, int height, const void *src,
const int UVwidth = (width + 1) / 2;
const int UVheight = (height + 1) / 2;
const int srcUVPitch = ((src_pitch + 1) / 2) * 2;
const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2) / sizeof(Uint16);
const int dstUVPitch = ((dst_pitch + 1) / 2) * 2;
const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2) / sizeof(Uint16);
const Uint16 *srcUV;
Uint16 *dstUV;
// Skip the Y plane
src = (const Uint8 *)src + height * src_pitch;
dst = (Uint8 *)dst + height * dst_pitch;
srcUV = (const Uint16 *)src;
dstUV = (Uint16 *)dst;
y = UVheight;
while (y--) {
x = UVwidth;
while (x--) {
*dstUV++ = SDL_Swap16(*srcUV++);
bool aligned = (((uintptr_t)src | (uintptr_t)dst) & 1) == 0;
if (aligned) {
const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2) / sizeof(Uint16);
const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2) / sizeof(Uint16);
const Uint16 *srcUV = (const Uint16 *)src;
Uint16 *dstUV = (Uint16 *)dst;
y = UVheight;
while (y--) {
x = UVwidth;
while (x--) {
*dstUV++ = SDL_Swap16(*srcUV++);
}
srcUV += srcUVPitchLeft;
dstUV += dstUVPitchLeft;
}
} else {
const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2);
const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2);
const Uint8 *srcUV = (const Uint8 *)src;
Uint8 *dstUV = (Uint8 *)dst;
y = UVheight;
while (y--) {
x = UVwidth;
while (x--) {
Uint8 u = *srcUV++;
Uint8 v = *srcUV++;
*dstUV++ = v;
*dstUV++ = u;
}
srcUV += srcUVPitchLeft;
dstUV += dstUVPitchLeft;
}
srcUV += srcUVPitchLeft;
dstUV += dstUVPitchLeft;
}
return true;
}
+19 -15
View File
@@ -556,22 +556,24 @@ bool Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, S
bool Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
{
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->internal;
NSScreen *screen = GetNSScreenForDisplayID(displaydata->display);
@autoreleasepool {
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->internal;
NSScreen *screen = GetNSScreenForDisplayID(displaydata->display);
if (screen == nil) {
return SDL_SetError("Couldn't get NSScreen for display");
if (screen == nil) {
return SDL_SetError("Couldn't get NSScreen for display");
}
{
const NSRect frame = [screen visibleFrame];
rect->x = (int)frame.origin.x;
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
rect->w = (int)frame.size.width;
rect->h = (int)frame.size.height;
}
return true;
}
{
const NSRect frame = [screen visibleFrame];
rect->x = (int)frame.origin.x;
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
rect->w = (int)frame.size.width;
rect->h = (int)frame.size.height;
}
return true;
}
bool Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
@@ -644,7 +646,9 @@ static CGError SetDisplayModeForDisplay(CGDirectDisplayID display, SDL_DisplayMo
result = CGDisplaySetDisplayMode(display, moderef, NULL);
if (result == kCGErrorSuccess) {
// If this mode works, try it first next time.
CFArrayExchangeValuesAtIndices(data->modes, i, 0);
if (i > 0) {
CFArrayExchangeValuesAtIndices(data->modes, i, 0);
}
break;
}
}
+42 -47
View File
@@ -868,14 +868,16 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
return NO; // we only allow you to make a Space on fullscreen desktop windows.
} else if (!state && window->last_fullscreen_exclusive_display) {
return NO; // we only handle leaving the Space on windows that were previously fullscreen desktop.
} else if (state == isFullscreenSpace) {
} else if (state == isFullscreenSpace && !inFullscreenTransition) {
return YES; // already there.
}
if (inFullscreenTransition) {
if (state) {
[self clearPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
[self addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
} else {
[self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
[self addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
}
return YES;
@@ -903,6 +905,11 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
pendingWindowOperation &= ~operation;
}
- (void)clearAllPendingWindowOperations
{
pendingWindowOperation = PENDING_OPERATION_NONE;
}
- (void)addPendingWindowOperation:(PendingWindowOperation)operation
{
pendingWindowOperation |= operation;
@@ -915,7 +922,8 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
- (BOOL)hasPendingWindowOperation
{
return pendingWindowOperation != PENDING_OPERATION_NONE ||
// A pending zoom may be deferred until leaving fullscreen, so don't block on it.
return (pendingWindowOperation & ~PENDING_OPERATION_ZOOM) != PENDING_OPERATION_NONE ||
isMiniaturizing || inFullscreenTransition;
}
@@ -1349,21 +1357,14 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
inFullscreenTransition = YES;
}
/* This is usually sent after an unexpected windowDidExitFullscreen if the window
* failed to become fullscreen.
*
* Since something went wrong and the current state is unknown, dump any pending events.
*/
- (void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification
{
SDL_Window *window = _data.window;
if (window->is_destroying) {
return;
}
SetWindowStyle(window, GetWindowStyle(window));
[self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
isFullscreenSpace = NO;
inFullscreenTransition = NO;
[self windowDidExitFullScreen:nil];
[self clearAllPendingWindowOperations];
}
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
@@ -1371,6 +1372,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
SDL_Window *window = _data.window;
inFullscreenTransition = NO;
isFullscreenSpace = YES;
[self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
if ([self windowOperationIsPending:PENDING_OPERATION_LEAVE_FULLSCREEN]) {
@@ -1421,26 +1423,14 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
inFullscreenTransition = YES;
}
/* This may be sent before windowDidExitFullscreen to signal that the window was
* dumped out of fullscreen with no animation.
*
* Since something went wrong and the state is unknown, dump any pending events.
*/
- (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
{
SDL_Window *window = _data.window;
const NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
if (window->is_destroying) {
return;
}
_data.pending_position = NO;
_data.pending_size = NO;
window->last_position_pending = false;
window->last_size_pending = false;
SetWindowStyle(window, flags);
isFullscreenSpace = YES;
inFullscreenTransition = NO;
[self windowDidEnterFullScreen:nil];
[self clearAllPendingWindowOperations];
}
- (void)windowDidExitFullScreen:(NSNotification *)aNotification
@@ -1449,16 +1439,24 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
NSWindow *nswindow = _data.nswindow;
inFullscreenTransition = NO;
isFullscreenSpace = NO;
_data.fullscreen_space_requested = NO;
/* As of macOS 10.15, the window decorations can go missing sometimes after
certain fullscreen-desktop->exlusive-fullscreen->windowed mode flows
certain fullscreen-desktop->exclusive-fullscreen->windowed mode flows
sometimes. Making sure the style mask always uses the windowed mode style
when returning to windowed mode from a space (instead of using a pending
fullscreen mode style mask) seems to work around that issue.
*/
SetWindowStyle(window, GetWindowWindowedStyle(window));
/* This can happen if the window failed to enter fullscreen, as this
* may be called *before* windowDidFailToEnterFullScreen in that case.
*/
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
[self clearAllPendingWindowOperations];
}
/* Don't recurse back into UpdateFullscreenMode() if this was hit in
* a blocking transition, as the caller is already waiting in
* UpdateFullscreenMode().
@@ -1503,9 +1501,10 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
if ([self windowOperationIsPending:PENDING_OPERATION_ZOOM]) {
[self clearPendingWindowOperation:PENDING_OPERATION_ZOOM];
[nswindow zoom:nil];
_data.was_zoomed = !_data.was_zoomed;
}
if (![nswindow isZoomed]) {
if (!_data.was_zoomed) {
// Apply a pending window size, if not zoomed.
NSRect rect;
rect.origin.x = _data.pending_position ? window->pending.x : window->floating.x;
@@ -2125,6 +2124,7 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
if (!data) {
return SDL_OutOfMemory();
}
window->internal = (SDL_WindowData *)CFBridgingRetain(data);
data.window = window;
data.nswindow = nswindow;
data.videodata = videodata;
@@ -2245,7 +2245,6 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER, SDL_METALVIEW_TAG);
// All done!
window->internal = (SDL_WindowData *)CFBridgingRetain(data);
return true;
}
}
@@ -3260,25 +3259,21 @@ bool Cocoa_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float op
bool Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
bool result = true;
bool result = false;
@autoreleasepool {
/* The timeout needs to be high enough that animated fullscreen
* spaces transitions won't cause it to time out.
*/
Uint64 timeout = SDL_GetTicksNS() + SDL_MS_TO_NS(2000);
const Uint64 timeout = SDL_GetTicksNS() + SDL_MS_TO_NS(2500);
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
while (true) {
for (;;) {
SDL_PumpEvents();
if (SDL_GetTicksNS() >= timeout) {
result = false;
break;
}
if (![data.listener hasPendingWindowOperation]) {
result = ![data.listener hasPendingWindowOperation];
if (result || SDL_GetTicksNS() >= timeout) {
break;
}
// Small delay before going again.
SDL_Delay(10);
}
}
@@ -1005,6 +1005,27 @@ static void Emscripten_unset_drag_event_callbacks(SDL_WindowData *data)
}, data->canvas_id);
}
static const char *Emscripten_GetKeyboardTargetElement()
{
const char *target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
if (!target || !*target) {
return EMSCRIPTEN_EVENT_TARGET_WINDOW;
}
if (SDL_strcmp(target, "#none") == 0) {
return NULL;
} else if (SDL_strcmp(target, "#window") == 0) {
return EMSCRIPTEN_EVENT_TARGET_WINDOW;
} else if (SDL_strcmp(target, "#document") == 0) {
return EMSCRIPTEN_EVENT_TARGET_DOCUMENT;
} else if (SDL_strcmp(target, "#screen") == 0) {
return EMSCRIPTEN_EVENT_TARGET_SCREEN;
}
return target;
}
void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
{
const char *keyElement;
@@ -1033,12 +1054,8 @@ void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, data, 0, Emscripten_HandlePointerLockChange);
// Keyboard events are awkward
keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
if (!keyElement || !*keyElement) {
keyElement = EMSCRIPTEN_EVENT_TARGET_WINDOW;
}
if (SDL_strcmp(keyElement, "#none") != 0) {
keyElement = Emscripten_GetKeyboardTargetElement();
if (keyElement) {
emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey);
emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey);
emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress);
@@ -1094,12 +1111,8 @@ void Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, 0, NULL);
target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
if (!target || !*target) {
target = EMSCRIPTEN_EVENT_TARGET_WINDOW;
}
if (SDL_strcmp(target, "#none") != 0) {
target = Emscripten_GetKeyboardTargetElement();
if (target) {
emscripten_set_keydown_callback(target, NULL, 0, NULL);
emscripten_set_keyup_callback(target, NULL, 0, NULL);
emscripten_set_keypress_callback(target, NULL, 0, NULL);
@@ -37,6 +37,7 @@
#include "SDL_uikitvulkan.h"
#include "SDL_uikitmetalview.h"
#include "SDL_uikitmessagebox.h"
#include "SDL_uikitpen.h"
#define UIKITVID_DRIVER_NAME "uikit"
@@ -170,6 +171,7 @@ static void UIKit_VideoQuit(SDL_VideoDevice *_this)
SDL_QuitGCKeyboard();
SDL_QuitGCMouse();
UIKit_QuitPen(_this);
UIKit_QuitModes(_this);
}
@@ -1023,8 +1023,8 @@ static void relative_pointer_handle_relative_motion(void *data,
dx = wl_fixed_to_double(dx_unaccel_w);
dy = wl_fixed_to_double(dy_unaccel_w);
} else {
dx = wl_fixed_to_double(dx_w);
dy = wl_fixed_to_double(dy_w);
dx = wl_fixed_to_double(dx_w) * window->pointer_scale.x;
dy = wl_fixed_to_double(dy_w) * window->pointer_scale.y;
}
SDL_SendMouseMotion(timestamp, window->sdlwindow, input->pointer_id, true, (float)dx, (float)dy);
@@ -1884,7 +1884,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, input->keyboard_id, key, scancode, state == WL_KEYBOARD_KEY_STATE_PRESSED);
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
if (has_text && !(SDL_GetModState() & SDL_KMOD_CTRL)) {
if (has_text && !(SDL_GetModState() & (SDL_KMOD_CTRL | SDL_KMOD_ALT))) {
if (!handled_by_ime) {
SDL_SendKeyboardText(text);
}
@@ -3304,6 +3304,11 @@ bool Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *w
return SDL_SetError("No pointer to confine");
}
// The confinement region will be created when the window is mapped.
if (w->shell_surface_status != WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
return true;
}
/* A confine may already be active, in which case we should destroy it and
* create a new one.
*/
@@ -3353,6 +3358,9 @@ bool Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *w
wl_region_destroy(confine_rect);
}
// Commit the double-buffered confinement region.
wl_surface_commit(w->surface);
w->confined_pointer = confined_pointer;
return true;
}
@@ -903,6 +903,7 @@ static SDL_MouseButtonFlags SDLCALL Wayland_GetGlobalMouseState(float *x, float
int off_x, off_y;
result = viddata->input->buttons_pressed;
SDL_GetMouseState(x, y);
SDL_RelativeToGlobalForWindow(focus, focus->x, focus->y, &off_x, &off_y);
*x += off_x;
*y += off_y;
@@ -707,6 +707,9 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
}
}
// Create the pointer confinement region, if necessary.
Wayland_input_confine_pointer(wind->waylandData->input, wind->sdlwindow);
/* If the window was initially set to the suspended state, send the occluded event now,
* as we don't want to mark the window as occluded until at least one frame has been submitted.
*/
@@ -2299,8 +2302,8 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win
}
// Don't send redundant fullscreen set/unset events.
if (fullscreen != wind->is_fullscreen) {
wind->fullscreen_was_positioned = fullscreen;
if (!!fullscreen != wind->is_fullscreen) {
wind->fullscreen_was_positioned = !!fullscreen;
SetFullscreen(window, fullscreen ? output : NULL);
} else if (wind->is_fullscreen) {
/*
@@ -620,7 +620,7 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL
SDL_WindowData *windowdata = window->internal;
if (haveMotion) {
if (haveMotion && !windowdata->in_modal_loop) {
if (!isAbsolute) {
SDL_SendMouseMotion(timestamp, window, mouseID, true, (float)dx, (float)dy);
} else {
@@ -1640,7 +1640,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
POINT cursorPos;
GetCursorPos(&cursorPos);
ScreenToClient(hwnd, &cursorPos);
PostMessage(hwnd, WM_MOUSEMOVE, 0, cursorPos.x | cursorPos.y << 16);
PostMessage(hwnd, WM_MOUSEMOVE, 0, cursorPos.x | (((Uint32)((Sint16)cursorPos.y)) << 16));
}
} break;
@@ -1792,7 +1792,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
}
if (!data->disable_move_size_events) {
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
ClientToScreen(hwnd, (LPPOINT) &rect);
ClientToScreen(hwnd, (LPPOINT) &rect + 1);
@@ -1804,7 +1804,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
}
// Moving the window from one display to another can change the size of the window (in the handling of SDL_EVENT_WINDOW_MOVED), so we need to re-query the bounds
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
w = rect.right;
h = rect.bottom;
@@ -1859,6 +1859,15 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
{
if (wParam == (UINT_PTR)SDL_IterateMainCallbacks) {
SDL_OnWindowLiveResizeUpdate(data->window);
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
#if 0 // This locks up the Windows compositor when called by Steam; disabling until we understand why
// Make sure graphics operations are complete for smooth refresh
if (data->videodata->DwmFlush) {
data->videodata->DwmFlush();
}
#endif
#endif
return 0;
}
} break;
@@ -2084,7 +2093,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
RECT rect;
float x, y;
if (!GetClientRect(hwnd, &rect) || WIN_IsRectEmpty(&rect)) {
if (!GetClientRect(hwnd, &rect) || !WIN_WindowRectValid(&rect)) {
if (inputs) {
SDL_small_free(inputs, isstack);
}
@@ -108,6 +108,9 @@ static void WIN_DeleteDevice(SDL_VideoDevice *device)
if (data->shcoreDLL) {
SDL_UnloadObject(data->shcoreDLL);
}
if (data->dwmapiDLL) {
SDL_UnloadObject(data->dwmapiDLL);
}
#endif
#ifdef HAVE_DXGI_H
if (data->pDXGIFactory) {
@@ -184,6 +187,17 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
} else {
SDL_ClearError();
}
data->dwmapiDLL = SDL_LoadObject("DWMAPI.DLL");
if (data->dwmapiDLL) {
/* *INDENT-OFF* */ // clang-format off
data->DwmFlush = (HRESULT (WINAPI *)(void))SDL_LoadFunction(data->dwmapiDLL, "DwmFlush");
data->DwmEnableBlurBehindWindow = (HRESULT (WINAPI *)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind))SDL_LoadFunction(data->dwmapiDLL, "DwmEnableBlurBehindWindow");
data->DwmSetWindowAttribute = (HRESULT (WINAPI *)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute))SDL_LoadFunction(data->dwmapiDLL, "DwmSetWindowAttribute");
/* *INDENT-ON* */ // clang-format on
} else {
SDL_ClearError();
}
#endif // #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
#ifdef HAVE_DXGI_H
@@ -374,6 +374,45 @@ typedef struct tagINPUTCONTEXT2
} INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;
#endif
// Corner rounding support (Win 11+)
#ifndef DWMWA_WINDOW_CORNER_PREFERENCE
#define DWMWA_WINDOW_CORNER_PREFERENCE 33
#endif
typedef enum {
DWMWCP_DEFAULT = 0,
DWMWCP_DONOTROUND = 1,
DWMWCP_ROUND = 2,
DWMWCP_ROUNDSMALL = 3
} DWM_WINDOW_CORNER_PREFERENCE;
// Border Color support (Win 11+)
#ifndef DWMWA_BORDER_COLOR
#define DWMWA_BORDER_COLOR 34
#endif
#ifndef DWMWA_COLOR_DEFAULT
#define DWMWA_COLOR_DEFAULT 0xFFFFFFFF
#endif
#ifndef DWMWA_COLOR_NONE
#define DWMWA_COLOR_NONE 0xFFFFFFFE
#endif
// Transparent window support
#ifndef DWM_BB_ENABLE
#define DWM_BB_ENABLE 0x00000001
#endif
#ifndef DWM_BB_BLURREGION
#define DWM_BB_BLURREGION 0x00000002
#endif
typedef struct
{
DWORD flags;
BOOL enable;
HRGN blur_region;
BOOL transition_on_maxed;
} DWM_BLURBEHIND;
// Private display data
struct SDL_VideoData
@@ -420,6 +459,11 @@ struct SDL_VideoData
BOOL (WINAPI *GetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
BOOL (WINAPI *GetPointerPenInfo)(UINT32 pointerId, POINTER_PEN_INFO *penInfo);
SDL_SharedObject *dwmapiDLL;
/* *INDENT-OFF* */ // clang-format off
HRESULT (WINAPI *DwmFlush)(void);
HRESULT (WINAPI *DwmEnableBlurBehindWindow)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind);
HRESULT (WINAPI *DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
/* *INDENT-ON* */ // clang-format on
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
+29 -100
View File
@@ -38,10 +38,6 @@
// Dropfile support
#include <shellapi.h>
// DWM setting support
typedef HRESULT (WINAPI *DwmSetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
typedef HRESULT (WINAPI *DwmGetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
// Dark mode support
typedef enum {
UXTHEME_APPMODE_DEFAULT,
@@ -80,46 +76,6 @@ typedef UxthemePreferredAppMode (WINAPI *SetPreferredAppMode_t)(UxthemePreferred
typedef BOOL (WINAPI *SetWindowCompositionAttribute_t)(HWND, const WINDOWCOMPOSITIONATTRIBDATA *);
typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *);
// Corner rounding support (Win 11+)
#ifndef DWMWA_WINDOW_CORNER_PREFERENCE
#define DWMWA_WINDOW_CORNER_PREFERENCE 33
#endif
typedef enum {
DWMWCP_DEFAULT = 0,
DWMWCP_DONOTROUND = 1,
DWMWCP_ROUND = 2,
DWMWCP_ROUNDSMALL = 3
} DWM_WINDOW_CORNER_PREFERENCE;
// Border Color support (Win 11+)
#ifndef DWMWA_BORDER_COLOR
#define DWMWA_BORDER_COLOR 34
#endif
#ifndef DWMWA_COLOR_DEFAULT
#define DWMWA_COLOR_DEFAULT 0xFFFFFFFF
#endif
#ifndef DWMWA_COLOR_NONE
#define DWMWA_COLOR_NONE 0xFFFFFFFE
#endif
// Transparent window support
#ifndef DWM_BB_ENABLE
#define DWM_BB_ENABLE 0x00000001
#endif
#ifndef DWM_BB_BLURREGION
#define DWM_BB_BLURREGION 0x00000002
#endif
typedef struct
{
DWORD flags;
BOOL enable;
HRGN blur_region;
BOOL transition_on_maxed;
} DWM_BLURBEHIND;
typedef HRESULT(WINAPI *DwmEnableBlurBehindWindow_t)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind);
// Windows CE compatibility
#ifndef SWP_NOCOPYBITS
#define SWP_NOCOPYBITS 0
@@ -447,7 +403,6 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
data->videodata = videodata;
data->initializing = true;
data->last_displayID = window->last_displayID;
data->dwma_border_color = DWMWA_COLOR_DEFAULT;
data->hint_erase_background_mode = GetEraseBackgroundModeHint();
@@ -535,7 +490,7 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
}
if (!(window->flags & SDL_WINDOW_MINIMIZED)) {
RECT rect;
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
int w = rect.right;
int h = rect.bottom;
@@ -745,6 +700,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window, bool set_active_focus)
bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_VideoData *videodata = _this->internal;
HWND hwnd = (HWND)SDL_GetPointerProperty(create_props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, SDL_GetPointerProperty(create_props, "sdl2-compat.external_window", NULL));
HWND parent = NULL;
if (hwnd) {
@@ -806,24 +762,19 @@ bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
// FIXME: does not work on all hardware configurations with different renders (i.e. hybrid GPUs)
if (window->flags & SDL_WINDOW_TRANSPARENT) {
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
if (handle) {
DwmEnableBlurBehindWindow_t DwmEnableBlurBehindWindowFunc = (DwmEnableBlurBehindWindow_t)SDL_LoadFunction(handle, "DwmEnableBlurBehindWindow");
if (DwmEnableBlurBehindWindowFunc) {
/* The region indicates which part of the window will be blurred and rest will be transparent. This
is because the alpha value of the window will be used for non-blurred areas
We can use (-1, -1, 0, 0) boundary to make sure no pixels are being blurred
*/
HRGN rgn = CreateRectRgn(-1, -1, 0, 0);
DWM_BLURBEHIND bb;
bb.flags = (DWM_BB_ENABLE | DWM_BB_BLURREGION);
bb.enable = TRUE;
bb.blur_region = rgn;
bb.transition_on_maxed = FALSE;
DwmEnableBlurBehindWindowFunc(hwnd, &bb);
DeleteObject(rgn);
}
SDL_UnloadObject(handle);
if (videodata->DwmEnableBlurBehindWindow) {
/* The region indicates which part of the window will be blurred and rest will be transparent. This
is because the alpha value of the window will be used for non-blurred areas
We can use (-1, -1, 0, 0) boundary to make sure no pixels are being blurred
*/
HRGN rgn = CreateRectRgn(-1, -1, 0, 0);
DWM_BLURBEHIND bb;
bb.flags = (DWM_BB_ENABLE | DWM_BB_BLURREGION);
bb.enable = TRUE;
bb.blur_region = rgn;
bb.transition_on_maxed = FALSE;
videodata->DwmEnableBlurBehindWindow(hwnd, &bb);
DeleteObject(rgn);
}
}
@@ -1062,7 +1013,7 @@ void WIN_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *
HWND hwnd = data->hwnd;
RECT rect;
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
*w = rect.right;
*h = rect.bottom;
} else if (window->last_pixel_w && window->last_pixel_h) {
@@ -1265,42 +1216,20 @@ void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
}
static DWM_WINDOW_CORNER_PREFERENCE WIN_UpdateCornerRoundingForHWND(HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
static void WIN_UpdateCornerRoundingForHWND(SDL_VideoDevice *_this, HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
{
DWM_WINDOW_CORNER_PREFERENCE oldPref = DWMWCP_DEFAULT;
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
if (handle) {
DwmGetWindowAttribute_t DwmGetWindowAttributeFunc = (DwmGetWindowAttribute_t)SDL_LoadFunction(handle, "DwmGetWindowAttribute");
DwmSetWindowAttribute_t DwmSetWindowAttributeFunc = (DwmSetWindowAttribute_t)SDL_LoadFunction(handle, "DwmSetWindowAttribute");
if (DwmGetWindowAttributeFunc && DwmSetWindowAttributeFunc) {
DwmGetWindowAttributeFunc(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &oldPref, sizeof(oldPref));
DwmSetWindowAttributeFunc(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
}
SDL_UnloadObject(handle);
SDL_VideoData *videodata = _this->internal;
if (videodata->DwmSetWindowAttribute) {
videodata->DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
}
return oldPref;
}
static COLORREF WIN_UpdateBorderColorForHWND(HWND hwnd, COLORREF colorRef)
static void WIN_UpdateBorderColorForHWND(SDL_VideoDevice *_this, HWND hwnd, COLORREF colorRef)
{
COLORREF oldPref = DWMWA_COLOR_DEFAULT;
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
if (handle) {
DwmGetWindowAttribute_t DwmGetWindowAttributeFunc = (DwmGetWindowAttribute_t)SDL_LoadFunction(handle, "DwmGetWindowAttribute");
DwmSetWindowAttribute_t DwmSetWindowAttributeFunc = (DwmSetWindowAttribute_t)SDL_LoadFunction(handle, "DwmSetWindowAttribute");
if (DwmGetWindowAttributeFunc && DwmSetWindowAttributeFunc) {
DwmGetWindowAttributeFunc(hwnd, DWMWA_BORDER_COLOR, &oldPref, sizeof(oldPref));
DwmSetWindowAttributeFunc(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
}
SDL_UnloadObject(handle);
SDL_VideoData *videodata = _this->internal;
if (videodata->DwmSetWindowAttribute) {
videodata->DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
}
return oldPref;
}
/**
@@ -1311,7 +1240,7 @@ SDL_FullscreenResult WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
SDL_DisplayData *displaydata = display->internal;
SDL_WindowData *data = window->internal;
HWND hwnd = data->hwnd;
HWND hwnd = data ? data->hwnd : NULL;
MONITORINFO minfo;
DWORD style, styleEx;
HWND top;
@@ -1366,13 +1295,13 @@ SDL_FullscreenResult WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window
}
// Disable corner rounding & border color (Windows 11+) so the window fills the full screen
data->windowed_mode_corner_rounding = WIN_UpdateCornerRoundingForHWND(hwnd, DWMWCP_DONOTROUND);
data->dwma_border_color = WIN_UpdateBorderColorForHWND(hwnd, DWMWA_COLOR_NONE);
WIN_UpdateCornerRoundingForHWND(_this, hwnd, DWMWCP_DONOTROUND);
WIN_UpdateBorderColorForHWND(_this, hwnd, DWMWA_COLOR_NONE);
} else {
BOOL menu;
WIN_UpdateCornerRoundingForHWND(hwnd, (DWM_WINDOW_CORNER_PREFERENCE)data->windowed_mode_corner_rounding);
WIN_UpdateBorderColorForHWND(hwnd, data->dwma_border_color);
WIN_UpdateCornerRoundingForHWND(_this, hwnd, DWMWCP_DEFAULT);
WIN_UpdateBorderColorForHWND(_this, hwnd, DWMWA_COLOR_DEFAULT);
/* Restore window-maximization state, as applicable.
Special care is taken to *not* do this if and when we're
@@ -87,8 +87,6 @@ struct SDL_WindowData
RECT initial_size_rect;
RECT cursor_clipped_rect; // last successfully committed clipping rect for this window
RECT cursor_ctrlock_rect; // this is Windows-specific, but probably does not need to be per-window
UINT windowed_mode_corner_rounding;
COLORREF dwma_border_color;
bool mouse_tracked;
bool destroy_parent_with_window;
SDL_DisplayID last_displayID;
+2 -1
View File
@@ -977,7 +977,7 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
X11_HandleModifierKeys(videodata, scancode, true, true);
SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, true);
if (*text) {
if (*text && !(SDL_GetModState() & (SDL_KMOD_CTRL | SDL_KMOD_ALT))) {
text[text_length] = '\0';
X11_ClearComposition(windowdata);
SDL_SendKeyboardText(text);
@@ -2113,6 +2113,7 @@ void X11_PumpEvents(SDL_VideoDevice *_this)
SDL_LogError(SDL_LOG_CATEGORY_VIDEO,
"Time out elapsed after mode switch on display %" SDL_PRIu32 " with no window becoming fullscreen; reverting", _this->displays[i]->id);
SDL_SetDisplayModeForDisplay(_this->displays[i], NULL);
_this->displays[i]->internal->mode_switch_deadline_ns = 0;
}
}
}
+22 -12
View File
@@ -48,13 +48,17 @@
static const char g_MessageBoxFontLatin1[] =
"-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
static const char g_MessageBoxFont[] =
"-*-*-medium-r-normal--*-120-*-*-*-*-iso10646-1," // explicitly unicode (iso10646-1)
"-*-*-medium-r-*--*-120-*-*-*-*-iso10646-1," // explicitly unicode (iso10646-1)
"-*-*-*-*-*--*-*-*-*-*-*-iso10646-1," // just give me anything Unicode.
"-*-*-medium-r-normal--*-120-*-*-*-*-iso8859-1," // explicitly latin1, in case low-ASCII works out.
"-*-*-medium-r-*--*-120-*-*-*-*-iso8859-1," // explicitly latin1, in case low-ASCII works out.
"-*-*-*-*-*--*-*-*-*-*-*-iso8859-1"; // just give me anything latin1.
static const char* g_MessageBoxFont[] = {
"-*-*-medium-r-normal--*-120-*-*-*-*-iso10646-1", // explicitly unicode (iso10646-1)
"-*-*-medium-r-*--*-120-*-*-*-*-iso10646-1", // explicitly unicode (iso10646-1)
"-misc-*-*-*-*--*-*-*-*-*-*-iso10646-1", // misc unicode (fix for some systems)
"-*-*-*-*-*--*-*-*-*-*-*-iso10646-1", // just give me anything Unicode.
"-*-*-medium-r-normal--*-120-*-*-*-*-iso8859-1", // explicitly latin1, in case low-ASCII works out.
"-*-*-medium-r-*--*-120-*-*-*-*-iso8859-1", // explicitly latin1, in case low-ASCII works out.
"-misc-*-*-*-*--*-*-*-*-*-*-iso8859-1", // misc latin1 (fix for some systems)
"-*-*-*-*-*--*-*-*-*-*-*-iso8859-1", // just give me anything latin1.
NULL
};
static const SDL_MessageBoxColor g_default_colors[SDL_MESSAGEBOX_COLOR_COUNT] = {
{ 56, 54, 53 }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,
@@ -200,13 +204,19 @@ static bool X11_MessageBoxInit(SDL_MessageBoxDataX11 *data, const SDL_MessageBox
if (SDL_X11_HAVE_UTF8) {
char **missing = NULL;
int num_missing = 0;
data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont,
&missing, &num_missing, NULL);
if (missing) {
X11_XFreeStringList(missing);
int i_font;
for (i_font = 0; g_MessageBoxFont[i_font]; ++i_font) {
data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont[i_font],
&missing, &num_missing, NULL);
if (missing) {
X11_XFreeStringList(missing);
}
if (data->font_set) {
break;
}
}
if (!data->font_set) {
return SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
return SDL_SetError("Couldn't load x11 message box font");
}
} else
#endif
+63 -9
View File
@@ -555,22 +555,73 @@ static XRRScreenResources *X11_GetScreenResources(Display *dpy, int screen)
static void X11_CheckDisplaysMoved(SDL_VideoDevice *_this, Display *dpy)
{
const int screen = DefaultScreen(dpy);
XRRScreenResources *res = X11_GetScreenResources(dpy, screen);
if (!res) {
const int screencount = ScreenCount(dpy);
SDL_DisplayID *displays = SDL_GetDisplays(NULL);
if (!displays) {
return;
}
SDL_DisplayID *displays = SDL_GetDisplays(NULL);
if (displays) {
for (int screen = 0; screen < screencount; ++screen) {
XRRScreenResources *res = X11_GetScreenResources(dpy, screen);
if (!res) {
continue;
}
for (int i = 0; displays[i]; ++i) {
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
const SDL_DisplayData *displaydata = display->internal;
X11_UpdateXRandRDisplay(_this, dpy, screen, displaydata->xrandr_output, res, display);
if (displaydata->screen == screen) {
X11_UpdateXRandRDisplay(_this, dpy, screen, displaydata->xrandr_output, res, display);
}
}
SDL_free(displays);
X11_XRRFreeScreenResources(res);
}
X11_XRRFreeScreenResources(res);
SDL_free(displays);
}
static void X11_CheckDisplaysRemoved(SDL_VideoDevice *_this, Display *dpy)
{
const int screencount = ScreenCount(dpy);
int num_displays = 0;
SDL_DisplayID *displays = SDL_GetDisplays(&num_displays);
if (!displays) {
return;
}
for (int screen = 0; screen < screencount; ++screen) {
XRRScreenResources *res = X11_GetScreenResources(dpy, screen);
if (!res) {
continue;
}
for (int output = 0; output < res->noutput; output++) {
for (int i = 0; i < num_displays; ++i) {
if (!displays[i]) {
// We already removed this display from the list
continue;
}
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
const SDL_DisplayData *displaydata = display->internal;
if (displaydata->xrandr_output == res->outputs[output]) {
// This display is active, remove it from the list
displays[i] = 0;
break;
}
}
}
X11_XRRFreeScreenResources(res);
}
for (int i = 0; i < num_displays; ++i) {
if (displays[i]) {
// This display wasn't in the XRandR list
SDL_DelVideoDisplay(displays[i], true);
}
}
SDL_free(displays);
}
static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutputChangeNotifyEvent *ev)
@@ -580,9 +631,12 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput
int i;
#if 0
printf("XRROutputChangeNotifyEvent! [output=%u, crtc=%u, mode=%u, rotation=%u, connection=%u]", (unsigned int) ev->output, (unsigned int) ev->crtc, (unsigned int) ev->mode, (unsigned int) ev->rotation, (unsigned int) ev->connection);
printf("XRROutputChangeNotifyEvent! [output=%u, crtc=%u, mode=%u, rotation=%u, connection=%u]\n", (unsigned int) ev->output, (unsigned int) ev->crtc, (unsigned int) ev->mode, (unsigned int) ev->rotation, (unsigned int) ev->connection);
#endif
// XWayland doesn't always send output disconnected events
X11_CheckDisplaysRemoved(_this, ev->display);
displays = SDL_GetDisplays(NULL);
if (displays) {
for (i = 0; displays[i]; ++i) {
+25 -2
View File
@@ -78,6 +78,23 @@ static bool X11_IsXWayland(Display *d)
return X11_XQueryExtension(d, "XWAYLAND", &opcode, &event, &error) == True;
}
static bool X11_CheckCurrentDesktop(const char *name)
{
SDL_Environment *env = SDL_GetEnvironment();
const char *desktopVar = SDL_GetEnvironmentVariable(env, "DESKTOP_SESSION");
if (desktopVar && SDL_strcasecmp(desktopVar, name) == 0) {
return true;
}
desktopVar = SDL_GetEnvironmentVariable(env, "XDG_CURRENT_DESKTOP");
if (desktopVar && SDL_strcasestr(desktopVar, name)) {
return true;
}
return false;
}
static SDL_VideoDevice *X11_CreateDevice(void)
{
SDL_VideoDevice *device;
@@ -256,8 +273,14 @@ static SDL_VideoDevice *X11_CreateDevice(void)
device->system_theme = SDL_SystemTheme_Get();
#endif
device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT |
VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS;
device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT;
/* Openbox doesn't send the new window dimensions when entering fullscreen, so the events must be synthesized.
* This is otherwise not wanted, as it can break fullscreen window positioning on multi-monitor configurations.
*/
if (!X11_CheckCurrentDesktop("openbox")) {
device->device_caps |= VIDEO_DEVICE_CAPS_SENDS_DISPLAY_CHANGES;
}
data->is_xwayland = X11_IsXWayland(x11_display);
if (data->is_xwayland) {
+36 -14
View File
@@ -521,7 +521,9 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
return false;
}
SetupWindowInput(_this, window);
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT, true)) {
SetupWindowInput(_this, window);
}
return true;
}
@@ -532,7 +534,7 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
}
const bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, false);
const bool use_resize_sync = (window->flags & SDL_WINDOW_VULKAN); /* doesn't work well with Vulkan */
const bool use_resize_sync = !(window->flags & SDL_WINDOW_VULKAN); /* doesn't work well with Vulkan */
SDL_WindowData *windowdata;
Display *display = data->display;
int screen = displaydata->screen;
@@ -1436,7 +1438,6 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_WindowData *data = window->internal;
Display *display = data->videodata->display;
bool bActivate = SDL_GetHintBoolean(SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN, true);
bool position_is_absolute = false;
bool set_position = false;
XEvent event;
@@ -1444,9 +1445,6 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
// Update the position in case the parent moved while we were hidden
X11_ConstrainPopup(window, true);
data->pending_position = true;
// Coordinates after X11_ConstrainPopup() are already in the global space.
position_is_absolute = true;
set_position = true;
}
@@ -1489,14 +1487,11 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
const int tx = data->pending_position ? window->pending.x : window->x;
const int ty = data->pending_position ? window->pending.y : window->y;
int x, y;
if (position_is_absolute) {
x = tx;
y = ty;
} else {
SDL_RelativeToGlobalForWindow(window,
tx - data->border_left, ty - data->border_top,
&x, &y);
}
SDL_RelativeToGlobalForWindow(window,
tx - data->border_left, ty - data->border_top,
&x, &y);
data->pending_position = false;
X11_XMoveWindow(display, data->xwindow, x, y);
}
@@ -2017,6 +2012,33 @@ bool X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, bool
return true;
}
/* GNOME needs the _XWAYLAND_MAY_GRAB_KEYBOARD message on XWayland:
*
* - message_type set to "_XWAYLAND_MAY_GRAB_KEYBOARD"
* - window set to the xid of the window on which the grab is to be issued
* - data.l[0] to a non-zero value
*
* The dconf setting `org/gnome/mutter/wayland/xwayland-allow-grabs` must be enabled as well.
*
* https://gitlab.gnome.org/GNOME/mutter/-/commit/5f132f39750f684c3732b4346dec810cd218d609
*/
if (_this->internal->is_xwayland) {
Atom _XWAYLAND_MAY_GRAB_ATOM = X11_XInternAtom(display, "_XWAYLAND_MAY_GRAB_KEYBOARD", False);
if (_XWAYLAND_MAY_GRAB_ATOM != None) {
XClientMessageEvent client_message;
client_message.type = ClientMessage;
client_message.window = data->xwindow;
client_message.format = 32;
client_message.message_type = _XWAYLAND_MAY_GRAB_ATOM;
client_message.data.l[0] = 1;
client_message.data.l[1] = CurrentTime;
X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureNotifyMask | SubstructureRedirectMask, (XEvent *)&client_message);
X11_XFlush(display);
}
}
X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
} else {